Repository: raydak-labs/configarr Branch: main Commit: bf579b515124 Files: 236 Total size: 2.4 MB Directory structure: gitextract_5pq2jiy7/ ├── .claude/ │ ├── PROJECT_GUIDE.md │ └── settings.json ├── .dockerignore ├── .env.template ├── .github/ │ ├── FUNDING.yml │ ├── renovate.json5 │ └── workflows/ │ ├── build.yml │ ├── cli-release.yml │ ├── doc-preview.yml │ ├── documentation.yml │ ├── lint.yml │ └── release-it.yml ├── .gitignore ├── .prettierignore ├── .prettierrc.js ├── .release-it.json ├── .vscode/ │ ├── launch.json │ └── settings.json ├── AGENTS.md ├── CHANGELOG.md ├── CNAME ├── DEV.md ├── Dockerfile ├── Dockerfile-deno.Dockerfile ├── GEMINI.md ├── LICENSE ├── README.md ├── config.yml.template ├── custom/ │ └── cfs/ │ ├── custom-size-bigger-40gb.json │ ├── de-tier-01.json │ ├── de-tier-02.json │ ├── de-tier-03.json │ ├── lang-de-dl-2.json │ ├── lang-de-dl.json │ ├── lang-de-only.json │ ├── lang-en-only.json │ ├── lang-mic-dub.json │ └── lang-not-en-de.json ├── docs/ │ ├── .gitignore │ ├── README.md │ ├── docs/ │ │ ├── changelog.mdx │ │ ├── comparison.mdx │ │ ├── concepts.md │ │ ├── configuration/ │ │ │ ├── _category_.json │ │ │ ├── _include/ │ │ │ │ ├── config-file-sample.yml │ │ │ │ └── unmanaged-customformats.yml │ │ │ ├── config-file.md │ │ │ ├── environment-variables.md │ │ │ ├── experimental-support.md │ │ │ ├── general.md │ │ │ ├── scheduled.md │ │ │ └── telemetry.md │ │ ├── examples.md │ │ ├── faq.md │ │ ├── installation/ │ │ │ ├── _category_.json │ │ │ ├── _include/ │ │ │ │ └── docker-basic-conf.yml │ │ │ ├── binary.md │ │ │ ├── docker.md │ │ │ ├── kubernetes.md │ │ │ └── third-party.md │ │ ├── intro.mdx │ │ └── profiles/ │ │ └── index.mdx │ ├── docusaurus.config.ts │ ├── package.json │ ├── sidebars.ts │ ├── src/ │ │ ├── components/ │ │ │ └── HomepageFeatures/ │ │ │ ├── index.tsx │ │ │ └── styles.module.css │ │ ├── css/ │ │ │ └── custom.css │ │ └── pages/ │ │ ├── index.module.css │ │ ├── index.tsx │ │ └── markdown-page.md │ ├── static/ │ │ ├── .nojekyll │ │ └── robots.txt │ └── tsconfig.json ├── esbuild.ts ├── examples/ │ ├── full/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── cfs/ │ │ │ └── custom-size-bigger-40gb.json │ │ ├── docker-compose.jobs.yml │ │ ├── docker-compose.local.yml │ │ ├── docker-compose.yml │ │ ├── lidarr.xml │ │ ├── radarr.xml │ │ ├── readarr.xml │ │ ├── sonarr.xml │ │ ├── templates/ │ │ │ ├── lidarr.yml │ │ │ ├── radarr-cf.yml │ │ │ ├── radarr-quality.yml │ │ │ ├── readarr.yml │ │ │ ├── sonarr-cf.yml │ │ │ ├── sonarr-quality.yml │ │ │ └── whisparr.yml │ │ └── whisparr.xml │ └── scheduled/ │ ├── .gitignore │ ├── README.md │ ├── cron/ │ │ ├── configarr-reuse │ │ └── configarr-run │ ├── docker-compose.cron.yml │ ├── docker-compose.ofelia.yml │ ├── docker-compose.yml │ ├── ofelia.ini │ └── radarr.xml ├── flake.nix ├── generate-api.ts ├── package.json ├── pkgs/ │ └── nix/ │ ├── module/ │ │ ├── config.nix │ │ ├── default.nix │ │ └── options.nix │ └── package.nix ├── playwright.config.ts ├── secrets.yml.template ├── src/ │ ├── __generated__/ │ │ ├── lidarr/ │ │ │ ├── Api.ts │ │ │ ├── Content.ts │ │ │ ├── Feed.ts │ │ │ ├── Login.ts │ │ │ ├── Logout.ts │ │ │ ├── Path.ts │ │ │ ├── Ping.ts │ │ │ └── data-contracts.ts │ │ ├── radarr/ │ │ │ ├── Api.ts │ │ │ ├── Content.ts │ │ │ ├── Feed.ts │ │ │ ├── Login.ts │ │ │ ├── Logout.ts │ │ │ ├── Path.ts │ │ │ ├── Ping.ts │ │ │ └── data-contracts.ts │ │ ├── readarr/ │ │ │ ├── Api.ts │ │ │ ├── Content.ts │ │ │ ├── Feed.ts │ │ │ ├── Login.ts │ │ │ ├── Logout.ts │ │ │ ├── Path.ts │ │ │ ├── Ping.ts │ │ │ └── data-contracts.ts │ │ ├── sonarr/ │ │ │ ├── Api.ts │ │ │ ├── Content.ts │ │ │ ├── Feed.ts │ │ │ ├── Login.ts │ │ │ ├── Logout.ts │ │ │ ├── Path.ts │ │ │ ├── Ping.ts │ │ │ └── data-contracts.ts │ │ └── whisparr/ │ │ ├── Api.ts │ │ ├── Content.ts │ │ ├── Feed.ts │ │ ├── Login.ts │ │ ├── Logout.ts │ │ ├── Path.ts │ │ ├── Ping.ts │ │ └── data-contracts.ts │ ├── cache.ts │ ├── clients/ │ │ ├── lidarr-client.ts │ │ ├── radarr-client.ts │ │ ├── readarr-client.ts │ │ ├── sonarr-client.ts │ │ ├── unified-client.ts │ │ └── whisparr-client.ts │ ├── config.test.ts │ ├── config.ts │ ├── custom-formats.test.ts │ ├── custom-formats.ts │ ├── delay-profiles.test.ts │ ├── delay-profiles.ts │ ├── downloadClientConfig/ │ │ ├── downloadClientConfig.types.ts │ │ ├── downloadClientConfigSyncer.test.ts │ │ └── downloadClientConfigSyncer.ts │ ├── downloadClients/ │ │ ├── downloadClientBase.test.ts │ │ ├── downloadClientBase.ts │ │ ├── downloadClientGeneric.test.ts │ │ ├── downloadClientGeneric.ts │ │ ├── downloadClientSyncer.test.ts │ │ └── downloadClientSyncer.ts │ ├── env.ts │ ├── index.ts │ ├── ky-client.test.ts │ ├── ky-client.ts │ ├── local-importer.ts │ ├── logger.ts │ ├── media-management.ts │ ├── metadataProfiles/ │ │ ├── metadataProfile.types.ts │ │ ├── metadataProfileBase.test.ts │ │ ├── metadataProfileBase.ts │ │ ├── metadataProfileLidarr.test.ts │ │ ├── metadataProfileLidarr.ts │ │ ├── metadataProfileReadarr.test.ts │ │ ├── metadataProfileReadarr.ts │ │ └── metadataProfileSyncer.ts │ ├── quality-definitions.test.ts │ ├── quality-definitions.ts │ ├── quality-profiles.test.ts │ ├── quality-profiles.ts │ ├── recyclarr-importer.ts │ ├── remotePaths/ │ │ ├── remotePath.types.test.ts │ │ ├── remotePath.types.ts │ │ ├── remotePathSyncer.test.ts │ │ └── remotePathSyncer.ts │ ├── rootFolder/ │ │ ├── rootFolder.types.ts │ │ ├── rootFolderBase.test.ts │ │ ├── rootFolderBase.ts │ │ ├── rootFolderLidarr.test.ts │ │ ├── rootFolderLidarr.ts │ │ ├── rootFolderReadarr.test.ts │ │ ├── rootFolderReadarr.ts │ │ └── rootFolderSyncer.ts │ ├── tags.ts │ ├── telemetry.test.ts │ ├── telemetry.ts │ ├── trash-guide.test.ts │ ├── trash-guide.ts │ ├── types/ │ │ ├── arr.types.ts │ │ ├── common.types.ts │ │ ├── config.types.ts │ │ ├── download-client.types.ts │ │ ├── helper.types.ts │ │ ├── merged.types.ts │ │ ├── recyclarr.types.ts │ │ └── trashguide.types.ts │ ├── uiConfigs/ │ │ ├── uiConfig.types.ts │ │ ├── uiConfigSyncer.test.ts │ │ └── uiConfigSyncer.ts │ ├── url-template-importer.test.ts │ ├── url-template-importer.ts │ ├── util.test.ts │ └── util.ts ├── tests/ │ ├── e2e/ │ │ └── demo-todo-app.spec.ts │ └── samples/ │ ├── 20240930_cf_exceptLanguage.json │ ├── cfs.json │ ├── qualityDefinition.json │ ├── quality_profiles.json │ ├── quality_with_grouping.json │ ├── quality_without_grouping.json │ ├── single_custom_format.json │ └── single_quality_profile.json ├── tsconfig.json └── vitest.config.ts ================================================ FILE CONTENTS ================================================ ================================================ FILE: .claude/PROJECT_GUIDE.md ================================================ # Configarr - AI Agent Quick Start Guide ## Project Overview **Configarr** is a configuration and synchronization tool for \*arr applications (Sonarr, Radarr, Lidarr, Readarr, Whisparr). It integrates with TRaSH Guides to automate custom formats, quality profiles, and other settings. - **Language**: TypeScript (Node.js) - **Package Manager**: **pnpm** (always use `pnpm`, never `npm` or `yarn`) - **Build Tool**: esbuild - **Test Framework**: Vitest - **Code Style**: Prettier ## Quick Setup ```bash # Install dependencies pnpm install # Development pnpm start # Run the application pnpm test # Run tests pnpm test:watch # Run tests in watch mode pnpm build # Build for production pnpm lint # Check formatting pnpm lint:fix # Fix formatting pnpm typecheck # TypeScript type checking ``` ## Development Rules ### ✅ Must Do After Every Implementation 1. **Run all three checks** - ALL must pass before considering work complete: ```bash pnpm build && pnpm test && pnpm lint ``` 2. **Type checking** - Ensure no TypeScript errors: ```bash pnpm typecheck ``` ### 🎯 Coding Standards 1. **Follow Existing Patterns** - Study similar existing code before implementing new features - Maintain consistency with current architecture - Use established patterns (e.g., rootFolder pattern for new modules) 2. **TypeScript Best Practices** - Use strict typing - avoid `any` when possible - Prefer interfaces for public APIs, types for internal use - Use type inference where it improves readability - Leverage union types and discriminated unions - Use `unknown` instead of `any` for truly unknown types 3. **Architecture Patterns** - **Base Classes** - Abstract common logic (e.g., `BaseMetadataProfileSync`, `BaseRootFolderSync`) - **Type-Specific Implementations** - Extend base classes for each \*arr type - **Factory Pattern** - Use factories to instantiate correct implementation - **Syncer Pattern** - Orchestrate sync operations (create/update/delete) 4. **Code Organization** - Group related functionality in directories (e.g., `metadataProfiles/`, `rootFolder/`) - Use meaningful file names that reflect purpose - Keep client abstractions in `clients/` - Type definitions in `types/` or local `*.types.ts` files - Generated API code in `__generated__/` ## Project Structure ``` src/ ├── __generated__/ # Auto-generated API clients (don't modify) ├── clients/ # API client abstractions │ ├── unified-client.ts # Unified interface for all *arr types │ ├── radarr-client.ts │ ├── sonarr-client.ts │ └── ... ├── metadataProfiles/ # Metadata profiles sync (Lidarr/Readarr) │ ├── metadataProfileBase.ts │ ├── metadataProfileLidarr.ts │ ├── metadataProfileReadarr.ts │ └── metadataProfileSyncer.ts ├── rootFolder/ # Root folder sync ├── types/ # Type definitions │ ├── config.types.ts # Configuration types │ ├── common.types.ts # Shared types │ └── ... ├── config.ts # Configuration loading/merging ├── index.ts # Main entry point └── ... ``` ## Key Concepts ### \*arr Type Support The project supports multiple \*arr applications with varying feature support: - **Full Support**: Sonarr v4, Radarr v5 - **Experimental**: Lidarr, Readarr, Whisparr ### Unified Client Pattern All \*arr clients implement `IArrClient` interface: - Provides consistent API across different \*arr types - Optional methods for features not supported by all types (e.g., `getMetadataProfiles?()`) - Type-safe with generics for quality profiles, custom formats, etc. ### Configuration System - **YAML-based** configuration with `config.yml` - **Template support** - Recyclarr templates, TRaSH Guides, local files, URLs - **Secrets management** - `!secret`, `!env` and `!file` tags for sensitive data - **Type-safe** - Zod schemas for validation ### Sync Architecture Each feature (quality profiles, custom formats, metadata profiles, root folders) follows: 1. **Load** - Fetch current server state 2. **Calculate Diff** - Compare config vs. server 3. **Sync** - Create/update/delete resources 4. **Cleanup** - Optionally delete unmanaged items ## Testing - **Unit tests**: `*.test.ts` files alongside source - **Samples**: Test data in `tests/samples/` - **Mocking**: Use Vitest mocks for API clients - **Coverage**: Run `pnpm coverage` to check coverage ## Common Tasks ### Adding Support for New \*arr Feature 1. Check if unified client needs new optional methods 2. Create feature directory (e.g., `featureName/`) 3. Implement base class with abstract methods 4. Create type-specific implementations 5. Add factory function and syncer 6. Update main pipeline in `index.ts` 7. Add tests 8. Run: `pnpm build && pnpm test && pnpm lint && pnpm typecheck` ### Modifying Existing Feature 1. Locate relevant files (base class, implementations, syncer) 2. Make changes following existing patterns 3. Update tests 4. Run: `pnpm build && pnpm test && pnpm lint && pnpm typecheck` ### Adding New Configuration Options 1. Update types in `types/config.types.ts` 2. Update configuration merging in `config.ts` 3. Implement feature logic 4. Update documentation (if needed) 5. Run all checks ## Important Notes - **Never commit without passing all checks**: build, test, lint, typecheck - **Always use pnpm** - not npm or yarn - **Backward compatibility** - Maintain existing APIs when refactoring - **Type safety** - Prefer compile-time errors over runtime errors - **Logging** - Use the `logger` instance for consistent logging - **Error handling** - Graceful degradation, informative error messages ## Resources - **Documentation**: https://configarr.de - **Repository**: https://github.com/raydak-labs/configarr - **TRaSH Guides**: https://trash-guides.info/ - **Recyclarr Compatibility**: Config templates are compatible ## Getting Help When implementing new features: 1. Look for similar existing implementations 2. Follow established patterns (especially rootFolder/metadataProfiles) 3. Keep TypeScript strict typing 4. Test thoroughly 5. Ensure all checks pass ================================================ FILE: .claude/settings.json ================================================ { "permissions": { "allow": [ "Bash(pnpm test:*)", "Skill(superpowers:requesting-code-review)", "Bash(git rev-parse:*)", "Bash(pnpm run lint)", "Bash(pnpm run typecheck)", "Bash(pnpm typecheck)", "Bash(pnpm lint:fix:*)", "Bash(pnpm run build:*)", "Bash(gh pr view:*)", "Bash(git fetch:*)", "Bash(git add:*)", "Bash(git commit:*)", "Bash(pnpm build:*)", "Bash(pnpm lint:*)" ], "deny": [], "ask": [] } } ================================================ FILE: .dockerignore ================================================ node_modules .git .gitignore *.md dist repos dockerrepos playwright-report test-results config.yml secrets.yml ================================================ FILE: .env.template ================================================ #ROOT_PATH=/app #CUSTOM_REPO_ROOT=/app/repos #CONFIG_LOCATION=/app/config/config.yml #SECRETS_LOCATION=/app/config/secrets.yml #DRY_RUN=true # not fully supported yet #LOAD_LOCAL_SAMPLES=false #DEBUG_CREATE_FILES=false #LOG_LEVEL=info #TELEMETRY_ENABLED=false ================================================ FILE: .github/FUNDING.yml ================================================ ko_fi: blackdark93 github: blackdark ================================================ FILE: .github/renovate.json5 ================================================ { $schema: "https://docs.renovatebot.com/renovate-schema.json", extends: [ "config:recommended", "customManagers:githubActionsVersions", "schedule:monthly", ":prConcurrentLimitNone", ":prHourlyLimitNone", ":pinVersions", "security:minimumReleaseAgeNpm", ], ignorePaths: [ "**/node_modules/**", "**/bower_components/**", "**/vendor/**", "**/__tests__/**", "**/test/**", "**/tests/**", "**/__fixtures__/**", ], labels: ["dependencies"], packageRules: [ { matchUpdateTypes: ["minor", "patch", "pin"], automerge: true, addLabels: ["automerge"], }, { groupName: "devDependencies (non-major)", matchDepTypes: ["devDependencies"], matchUpdateTypes: ["patch", "minor"], }, { matchPackageNames: ["swagger-typescript-api"], groupName: null, }, { groupName: "dependencies (non-major)", matchDepTypes: ["dependencies"], matchUpdateTypes: ["patch", "minor"], }, { extends: ["monorepo:docusaurus"], groupName: "docusaurus monorepo", matchUpdateTypes: ["digest", "patch", "minor", "major"], }, { matchDatasources: ["docker"], matchUpdateTypes: ["minor", "patch"], groupName: "all docker updates (without major)", groupSlug: "all-docker", }, ], } ================================================ FILE: .github/workflows/build.yml ================================================ name: Docker Builds on: workflow_dispatch: push: branches: - "main" tags: - "v*.*.*" paths-ignore: - "docs/**" - "**/*.md" - ".github/**" - ".vscode/**" - "examples/**" permissions: contents: read packages: write # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: build: runs-on: ubuntu-latest steps: # Get the repositery's code - name: Checkout uses: actions/checkout@v6 - name: Inject enhanced GitHub environment variables uses: rlespinasse/github-slug-action@v5 # https://github.com/docker/setup-qemu-action - name: Set up QEMU uses: docker/setup-qemu-action@v4 with: image: tonistiigi/binfmt:qemu-v8.1.5 # more recent # https://github.com/docker/setup-buildx-action - name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v4 # We push and build all types of images only when required - name: Set build variables id: vars run: | # Set version based on tag or branch VERSION="${{ env.GITHUB_REF_SLUG }}" # Set build timestamp BUILD_TIME="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" echo "version=$VERSION" >> $GITHUB_OUTPUT echo "build_time=$BUILD_TIME" >> $GITHUB_OUTPUT echo "run_id=${{ github.run_id }}" >> $GITHUB_OUTPUT echo "repo=${{ github.repository }}" >> $GITHUB_OUTPUT echo "sha=${{ github.sha }}" >> $GITHUB_OUTPUT - name: Set build platforms id: set_platforms run: | if [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then echo "MANUAL_RUN=true" >> $GITHUB_OUTPUT else echo "MANUAL_RUN=false" >> $GITHUB_OUTPUT fi if [[ ${{ github.event_name }} == 'workflow_dispatch' || ${{ github.ref }} == refs/tags/* ]]; then echo "platforms=linux/amd64,linux/arm64" >> $GITHUB_OUTPUT echo "push=true" >> $GITHUB_OUTPUT else echo "platforms=linux/amd64" >> $GITHUB_OUTPUT echo "push=false" >> $GITHUB_OUTPUT fi # - name: Available platforms # run: echo ${{ steps.buildx.outputs.platforms }} - name: Login to GHCR if: github.event_name != 'pull_request' uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to Docker Hub if: github.event_name != 'pull_request' uses: docker/login-action@v4 with: username: ${{ vars.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Docker meta for PMS id: meta_pms uses: docker/metadata-action@v6 with: # list of Docker images to use as base name for tags images: | ghcr.io/raydak-labs/configarr docker.io/configarr/configarr,enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'false' }} # generate Docker tags based on the following events/attributes tags: | type=ref,event=branch,prefix=dev-,enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'true' }} type=schedule,enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'false' }} type=ref,event=branch,enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'false' }} type=semver,pattern={{version}},enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'false' }} type=semver,pattern={{major}}.{{minor}},enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'false' }} type=semver,pattern={{major}},enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'false' }} - name: Build and push PMS uses: docker/build-push-action@v7 with: context: . file: ./Dockerfile platforms: ${{ steps.set_platforms.outputs.platforms }} push: ${{ steps.set_platforms.outputs.push }} tags: ${{ steps.meta_pms.outputs.tags }} labels: ${{ steps.meta_pms.outputs.labels }} target: prod build-args: | CONFIGARR_VERSION=${{ steps.vars.outputs.version }} BUILD_TIME=${{ steps.vars.outputs.build_time }} GITHUB_RUN_ID=${{ steps.vars.outputs.run_id }} GITHUB_REPO=${{ steps.vars.outputs.repo }} GITHUB_SHA=${{ steps.vars.outputs.sha }} - name: Docker meta for alpine3.22 image id: meta_alpine322 uses: docker/metadata-action@v6 with: images: | ghcr.io/raydak-labs/configarr docker.io/configarr/configarr,enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'false' }} tags: | type=ref,event=branch,prefix=dev-,suffix=-alpine3.22,enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'true' }} type=schedule,suffix=-alpine3.22,enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'false' }} type=ref,event=branch,suffix=-alpine3.22,enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'false' }} type=semver,pattern={{version}},suffix=-alpine3.22,enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'false' }} type=semver,pattern={{major}}.{{minor}},suffix=-alpine3.22,enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'false' }} type=semver,pattern={{major}},suffix=-alpine3.22,enable=${{ steps.set_platforms.outputs.MANUAL_RUN == 'false' }} - name: Build and push alpine3.22 image uses: docker/build-push-action@v7 with: context: . file: ./Dockerfile platforms: ${{ steps.set_platforms.outputs.platforms }} push: ${{ steps.set_platforms.outputs.push }} tags: ${{ steps.meta_alpine322.outputs.tags }} labels: ${{ steps.meta_alpine322.outputs.labels }} target: prod-alpine-3-22 build-args: | CONFIGARR_VERSION=${{ steps.vars.outputs.version }} BUILD_TIME=${{ steps.vars.outputs.build_time }} GITHUB_RUN_ID=${{ steps.vars.outputs.run_id }} GITHUB_REPO=${{ steps.vars.outputs.repo }} GITHUB_SHA=${{ steps.vars.outputs.sha }} # - name: Docker Hub Description # if: github.event_name != 'pull_request' # uses: peter-evans/dockerhub-description@v3 # with: # username: ${{ secrets.DOCKERHUB_USERNAME }} # password: ${{ secrets.DOCKERHUB_PASSWORD }} # repository: pabloromeo/clusterplex_pms # readme-filepath: ./README.md # short-description: "PMS image for ClusterPlex" ================================================ FILE: .github/workflows/cli-release.yml ================================================ name: CLI Release on: push: tags: - "v*.*.*" workflow_dispatch: inputs: baseline: description: "Enable baseline builds for older CPU architectures" required: false type: boolean default: false permissions: contents: write jobs: build-cli: runs-on: ubuntu-latest strategy: matrix: include: - target: bun-linux-x64 platform: linux-x64 - target: bun-linux-arm64 platform: linux-arm64 - target: bun-darwin-x64 platform: darwin-x64 - target: bun-darwin-arm64 platform: darwin-arm64 - target: bun-windows-x64 platform: windows-x64 steps: - name: Checkout uses: actions/checkout@v6 - name: Inject enhanced GitHub environment variables uses: rlespinasse/github-slug-action@v5 - uses: pnpm/action-setup@v5 with: version: latest - uses: actions/setup-node@v6 with: node-version: lts/* cache: pnpm - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: Install deps run: | pnpm i - name: Set build variables id: vars run: | # Set version based on tag or branch VERSION="${{ env.GITHUB_REF_SLUG }}" # Set build timestamp BUILD_TIME="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" echo "version=$VERSION" >> $GITHUB_OUTPUT echo "build_time=$BUILD_TIME" >> $GITHUB_OUTPUT echo "run_id=${{ github.run_id }}" >> $GITHUB_OUTPUT echo "repo=${{ github.repository }}" >> $GITHUB_OUTPUT echo "sha=${{ github.sha }}" >> $GITHUB_OUTPUT - name: Build CLI run: | FLAGS="" # Set Windows-specific flags if building for Windows if [[ "${{ matrix.platform }}" == windows-* ]]; then # those flags are currently only supported when build in windows #FLAGS="${FLAGS} --windows-title \"Configarr\" --windows-publisher \"BlackDark\" --windows-version \"${{ steps.vars.outputs.version }}\" --windows-description \"A powerful configuration management tool for *Arr applications\" --windows-copyright \"© 2025 BlackDark\"" echo "No custom flags for windows" else FLAGS="${FLAGS} --bytecode" fi # Set baseline target if requested if [[ "${{ github.event.inputs.baseline }}" == "true" ]]; then FLAGS="${FLAGS} --target=bun" else echo "Non baseline build" fi echo "Using additional build flags: $FLAGS" bun build src/index.ts \ --compile --minify --sourcemap src/index.ts \ --outfile configarr \ --define 'process.env.CONFIGARR_VERSION="${{ steps.vars.outputs.version }}"' \ --define 'process.env.BUILD_TIME="${{ steps.vars.outputs.build_time }}"' \ --define 'process.env.GITHUB_RUN_ID="${{ steps.vars.outputs.run_id }}"' \ --define 'process.env.GITHUB_REPO="${{ steps.vars.outputs.repo }}"' \ --define 'process.env.GITHUB_SHA="${{ steps.vars.outputs.sha }}"' \ --define 'process.env.BUILD_PLATFORM="${{ matrix.platform }}"' \ --target=${{ matrix.target }} \ $FLAGS - name: Compress CLI run: tar -cJf configarr-${{ matrix.platform }}.tar.xz configarr* - name: Upload CLI artifact uses: actions/upload-artifact@v7 with: name: configarr-${{ matrix.platform }}.tar.xz path: configarr-${{ matrix.platform }}.tar.xz retention-days: 1 release: needs: build-cli if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest steps: - name: Download CLI artifacts uses: actions/download-artifact@v8 with: path: artifacts - name: Extract tar.gz files run: | find artifacts -name "*.tar.gz" -type f -exec sh -c ' dir=$(dirname "$1") base=$(basename "$1" .tar.gz) mkdir -p "$dir/extracted" tar -xzf "$1" -C "$dir/extracted" mv "$dir/extracted"/* "$dir/" 2>/dev/null || true rmdir "$dir/extracted" 2>/dev/null || true ' _ {} \; - name: Create Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ github.ref_name }} files: artifacts/**/configarr-*.tar.xz generate_release_notes: false ================================================ FILE: .github/workflows/doc-preview.yml ================================================ name: Documentation (Preview) on: pull_request: branches: [main] paths: - docs/** workflow_dispatch: jobs: deploy: runs-on: ubuntu-latest name: Deploy permissions: contents: read deployments: write pull-requests: write steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Inject enhanced GitHub environment variables uses: rlespinasse/github-slug-action@v5 - uses: pnpm/action-setup@v5 with: version: latest - uses: actions/setup-node@v6 with: node-version: lts/* cache: pnpm - name: Install & build working-directory: docs run: | pnpm i pnpm build - name: Deploy uses: cloudflare/wrangler-action@v3 id: cloudflare-deploy with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: pages deploy ./docs/build --project-name=configarr-preview --branch=${{ env.GITHUB_REF_SLUG_URL }} # Optional: Enable this if you want to have GitHub Deployments triggered #gitHubToken: ${{ secrets.GITHUB_TOKEN }} - name: Comment PR uses: thollander/actions-comment-pull-request@v3 if: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'main' }} with: message: | Doc preview deployed to: ${{ steps.cloudflare-deploy.outputs.deployment-url }} comment-tag: docs-preview ================================================ FILE: .github/workflows/documentation.yml ================================================ name: Documentation on: push: tags: - "v*.*.*" paths: - docs/** workflow_dispatch: jobs: build: name: Build runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - uses: pnpm/action-setup@v5 with: version: latest - uses: actions/setup-node@v6 with: node-version: lts/* cache: pnpm - name: Install & build working-directory: docs run: | pnpm i pnpm build - name: Upload static files as artifact id: deployment uses: actions/upload-pages-artifact@v4 # or specific "vX.X.X" version tag for this action with: path: ./docs/build # Deploy job deploy: if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' # Add a dependency to the build job needs: build # Grant GITHUB_TOKEN the permissions required to make a Pages deployment permissions: pages: write # to deploy to Pages id-token: write # to verify the deployment originates from an appropriate source # Deploy to the github-pages environment environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} # Specify runner + deployment step runs-on: ubuntu-latest steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v5 # or specific "vX.X.X" version tag for this action ================================================ FILE: .github/workflows/lint.yml ================================================ name: CI on: push: branches: - main pull_request: branches-ignore: - prod jobs: test: name: Lint & Test runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v6 - uses: pnpm/action-setup@v5 with: version: latest - uses: actions/setup-node@v6 with: node-version: lts/* cache: pnpm - run: pnpm install - name: Lint run: pnpm lint - name: Typecheck run: pnpm typecheck - name: Test run: pnpm test ================================================ FILE: .github/workflows/release-it.yml ================================================ name: release-it on: workflow_dispatch: jobs: release: runs-on: ubuntu-latest steps: - name: Generate a token id: generate_token uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0 with: app_id: ${{ secrets.RELEASER_APP_ID }} private_key: ${{ secrets.RELEASER_PRIVATE_KEY }} - name: Checkout code uses: actions/checkout@v6 with: token: ${{ steps.generate_token.outputs.token }} fetch-depth: 0 - name: git config run: | git config user.email "raydak-releaser@users.noreply.github.com" git config user.name "raydak-releaser[bot]" - uses: pnpm/action-setup@v5 with: version: latest - uses: actions/setup-node@v6 with: node-version: lts/* cache: pnpm - run: pnpm install - run: pnpm release-it --ci env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .gitignore ================================================ # Created by https://www.toptal.com/developers/gitignore/api/node # Edit at https://www.toptal.com/developers/gitignore?templates=node ### Node ### # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* .pnpm-debug.log* # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage *.lcov # nyc test coverage .nyc_output # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (https://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ jspm_packages/ # Snowpack dependency directory (https://snowpack.dev/) web_modules/ # TypeScript cache *.tsbuildinfo # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional stylelint cache .stylelintcache # Microbundle cache .rpt2_cache/ .rts2_cache_cjs/ .rts2_cache_es/ .rts2_cache_umd/ # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # Yarn Integrity file .yarn-integrity # dotenv environment variable files .env .env.development.local .env.test.local .env.production.local .env.local # parcel-bundler cache (https://parceljs.org/) .cache .parcel-cache # Next.js build output .next out # Nuxt.js build / generate output .nuxt dist # Gatsby files .cache/ # Comment in the public line in if your project uses Gatsby and not Next.js # https://nextjs.org/blog/next-9-1#public-directory-support # public # vuepress build output .vuepress/dist # vuepress v2.x temp and cache directory .temp # Docusaurus cache and generated files .docusaurus # Serverless directories .serverless/ # FuseBox cache .fusebox/ # DynamoDB Local files .dynamodb/ # TernJS port file .tern-port # Stores VSCode versions used for testing VSCode extensions .vscode-test # yarn v2 .yarn/cache .yarn/unplugged .yarn/build-state.yml .yarn/install-state.gz .pnp.* ### Node Patch ### # Serverless Webpack directories .webpack/ # Optional stylelint cache # SvelteKit build / generate output .svelte-kit # End of https://www.toptal.com/developers/gitignore/api/node *.env !.env.template /test-results/ /playwright-report/ /blob-report/ /playwright/.cache/ config.yml secrets.yml test*.json repos/ dockerrepos .DS_Store bundle.cjs *.bun-build cli-bun cli-deno result # Git worktrees .worktrees/ .claude/settings.local.json ================================================ FILE: .prettierignore ================================================ pnpm-lock.yaml docs/build ================================================ FILE: .prettierrc.js ================================================ /** @type {import("prettier").Options} */ export default { printWidth: 140, }; ================================================ FILE: .release-it.json ================================================ { "npm": false, "git": { "commitMessage": "chore: release ${version}", "requireCleanWorkingDir": false }, "github": { "release": true, "comments": { "submit": false } }, "plugins": { "@release-it/conventional-changelog": { "preset": { "name": "conventionalcommits", "types": [ { "type": "feat", "section": "Features" }, { "type": "fix", "section": "Bug Fixes" }, { "type": "refactor", "section": "(internal) Refactorings" } ] }, "infile": "CHANGELOG.md", "header": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n" } }, "hooks": { "before:git:release": ["pnpm exec prettier . --write", "git add .", "pnpm run lint"], "after:release": "echo \"RELEASED_VERSION=${version}\" >> $GITHUB_ENV" } } ================================================ FILE: .vscode/launch.json ================================================ { "version": "0.2.0", "configurations": [ { "command": "pnpm start", "name": "pnpm start", "request": "launch", "type": "node-terminal" }, { "name": "tsx", "type": "node", "request": "launch", // Debug current file in VSCode "program": "${file}", /* Path to tsx binary Assuming locally installed */ "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx", /* Open terminal when debugging starts (Optional) Useful to see console.logs */ "console": "integratedTerminal", "internalConsoleOptions": "neverOpen", // Files to exclude from debugger (e.g. call stack) "skipFiles": [ // Node.js internal core modules "/**", // Ignore all dependencies (optional) "${workspaceFolder}/node_modules/**" ] } ] } ================================================ FILE: .vscode/settings.json ================================================ { "yaml.customTags": ["!secret", "!env", "!file"] } ================================================ FILE: AGENTS.md ================================================ # Configarr - AI Agent Quick Start Guide ## Project Overview **Configarr** is a configuration and synchronization tool for \*arr applications (Sonarr, Radarr, Lidarr, Readarr, Whisparr). It integrates with TRaSH Guides to automate custom formats, quality profiles, and other settings. - **Language**: TypeScript (Node.js) - **Package Manager**: **pnpm** (always use `pnpm`, never `npm` or `yarn`) - **Build Tool**: esbuild - **Test Framework**: Vitest - **Code Style**: Prettier ## Quick Setup ```bash # Install dependencies pnpm install # Development pnpm start # Run the application pnpm test # Run tests pnpm test:watch # Run tests in watch mode pnpm build # Build for production pnpm lint # Check formatting pnpm lint:fix # Fix formatting pnpm typecheck # TypeScript type checking ``` ## Development Rules ### ✅ Must Do After Every Implementation 1. **Run all three checks** - ALL must pass before considering work complete: ```bash pnpm build && pnpm test && pnpm lint ``` 2. **Type checking** - Ensure no TypeScript errors: ```bash pnpm typecheck ``` ### 🎯 Coding Standards 1. **Follow Existing Patterns** - Study similar existing code before implementing new features - Maintain consistency with current architecture - Use established patterns (e.g., rootFolder pattern for new modules) 2. **TypeScript Best Practices** - Use strict typing - avoid `any` when possible - Prefer interfaces for public APIs, types for internal use - Use type inference where it improves readability - Leverage union types and discriminated unions - Use `unknown` instead of `any` for truly unknown types 3. **Architecture Patterns** - **Base Classes** - Abstract common logic (e.g., `BaseMetadataProfileSync`, `BaseRootFolderSync`) - **Type-Specific Implementations** - Extend base classes for each \*arr type - **Factory Pattern** - Use factories to instantiate correct implementation - **Syncer Pattern** - Orchestrate sync operations (create/update/delete) 4. **Code Organization** - Group related functionality in directories (e.g., `metadataProfiles/`, `rootFolder/`) - Use meaningful file names that reflect purpose - Keep client abstractions in `clients/` - Type definitions in `types/` or local `*.types.ts` files - Generated API code in `__generated__/` ## Project Structure ``` src/ ├── __generated__/ # Auto-generated API clients (don't modify) ├── clients/ # API client abstractions │ ├── unified-client.ts # Unified interface for all *arr types │ ├── radarr-client.ts │ ├── sonarr-client.ts │ └── ... ├── metadataProfiles/ # Metadata profiles sync (Lidarr/Readarr) │ ├── metadataProfileBase.ts │ ├── metadataProfileLidarr.ts │ ├── metadataProfileReadarr.ts │ └── metadataProfileSyncer.ts ├── rootFolder/ # Root folder sync ├── types/ # Type definitions │ ├── config.types.ts # Configuration types │ ├── common.types.ts # Shared types │ └── ... ├── config.ts # Configuration loading/merging ├── index.ts # Main entry point └── ... ``` ## Key Concepts ### \*arr Type Support The project supports multiple \*arr applications with varying feature support: - **Full Support**: Sonarr v4, Radarr v5 - **Experimental**: Lidarr, Readarr, Whisparr ### Unified Client Pattern All \*arr clients implement `IArrClient` interface: - Provides consistent API across different \*arr types - Optional methods for features not supported by all types (e.g., `getMetadataProfiles?()`) - Type-safe with generics for quality profiles, custom formats, etc. ### Configuration System - **YAML-based** configuration with `config.yml` - **Template support** - Recyclarr templates, TRaSH Guides, local files, URLs - **Secrets management** - `!secret`, `!env` and `!file` tags for sensitive data - **Type-safe** - Zod schemas for validation ### Sync Architecture Each feature (quality profiles, custom formats, metadata profiles, root folders) follows: 1. **Load** - Fetch current server state 2. **Calculate Diff** - Compare config vs. server 3. **Sync** - Create/update/delete resources 4. **Cleanup** - Optionally delete unmanaged items ## Testing - **Unit tests**: `*.test.ts` files alongside source - **Samples**: Test data in `tests/samples/` - **Mocking**: Use Vitest mocks for API clients - **Coverage**: Run `pnpm coverage` to check coverage ## Common Tasks ### Adding Support for New \*arr Feature 1. Check if unified client needs new optional methods 2. Create feature directory (e.g., `featureName/`) 3. Implement base class with abstract methods 4. Create type-specific implementations 5. Add factory function and syncer 6. Update main pipeline in `index.ts` 7. Add tests 8. Run: `pnpm build && pnpm test && pnpm lint && pnpm typecheck` ### Modifying Existing Feature 1. Locate relevant files (base class, implementations, syncer) 2. Make changes following existing patterns 3. Update tests 4. Run: `pnpm build && pnpm test && pnpm lint && pnpm typecheck` ### Adding New Configuration Options 1. Update types in `types/config.types.ts` 2. Update configuration merging in `config.ts` 3. Implement feature logic 4. Update documentation (if needed) 5. Run all checks ## Important Notes - **Never commit without passing all checks**: build, test, lint, typecheck - **Always use pnpm** - not npm or yarn - **Backward compatibility** - Maintain existing APIs when refactoring - **Type safety** - Prefer compile-time errors over runtime errors - **Logging** - Use the `logger` instance for consistent logging - **Error handling** - Graceful degradation, informative error messages ## Resources - **Documentation**: https://configarr.de - **Repository**: https://github.com/raydak-labs/configarr - **TRaSH Guides**: https://trash-guides.info/ - **Recyclarr Compatibility**: Config templates are compatible ## Getting Help When implementing new features: 1. Look for similar existing implementations 2. Follow established patterns (especially rootFolder/metadataProfiles) 3. Keep TypeScript strict typing 4. Test thoroughly 5. Ensure all checks pass ================================================ FILE: CHANGELOG.md ================================================ # Changelog All notable changes to this project will be documented in this file. ## [1.27.0](https://github.com/raydak-labs/configarr/compare/v1.26.0...v1.27.0) (2026-04-14) ### Features - add silenceTrashConflictWarnings config option ([b42072b](https://github.com/raydak-labs/configarr/commit/b42072bcff7d4532ba0ab42b749fbf1321fac0d9)) ## [1.26.0](https://github.com/raydak-labs/configarr/compare/v1.25.0...v1.26.0) (2026-04-13) ### Features - warn on TRaSH CF conflicts ([e5e7387](https://github.com/raydak-labs/configarr/commit/e5e738759a173e68152b53583ecbd846acf9aaa2)) ### Bug Fixes - address review findings in CF conflict handling ([92e807a](https://github.com/raydak-labs/configarr/commit/92e807a335cee08e675e0fed435ec66fa17f7a22)) - adjust conflicting cf names with different ids ([65c369d](https://github.com/raydak-labs/configarr/commit/65c369d9877e67534325a05ee7933d8309b44733)) - **deps:** update dependencies (non-major) ([#418](https://github.com/raydak-labs/configarr/issues/418)) ([50fff41](https://github.com/raydak-labs/configarr/commit/50fff41915bee98cd73b68aae025cca55dae9947)) - improve trash conflicts.json handling ([763ebef](https://github.com/raydak-labs/configarr/commit/763ebef84438f0fc13b76e6b8a6e0b9877704eff)) ### (internal) Refactorings - **internal:** move ky-client + mergedTypes from **generated** ([55acfd1](https://github.com/raydak-labs/configarr/commit/55acfd1ed7f2d0e19c6d158be5c122da69ce10d2)) - try improving error messages ([e5fcf78](https://github.com/raydak-labs/configarr/commit/e5fcf785b7094c5844a13d63141247a11502eb7a)) ## [1.25.0](https://github.com/raydak-labs/configarr/compare/v1.24.1...v1.25.0) (2026-03-30) ### Features - add support to include trash guide quality definitions by id ([#406](https://github.com/raydak-labs/configarr/issues/406)) ([c196221](https://github.com/raydak-labs/configarr/commit/c196221956e83b885d7228ad117986817c78ffe9)) ### Bug Fixes - prevent duplicate CF creates and fix error handling in manageCf ([7eff22e](https://github.com/raydak-labs/configarr/commit/7eff22efb9b20acbbd026fb47b3e13ea0ba0d3e0)) ## [1.24.1](https://github.com/raydak-labs/configarr/compare/v1.24.0...v1.24.1) (2026-03-29) ### Bug Fixes - introduce alpine3.22 images ([#411](https://github.com/raydak-labs/configarr/issues/411)) ([7f6a899](https://github.com/raydak-labs/configarr/commit/7f6a899ffab8f962d34e58d98c7d3f8f68342ff5)) ## [1.24.0](https://github.com/raydak-labs/configarr/compare/v1.23.0...v1.24.0) (2026-03-09) ### Features - add use_default_score flag to override CF scores ([#397](https://github.com/raydak-labs/configarr/issues/397)) ([3d7deeb](https://github.com/raydak-labs/configarr/commit/3d7deebd0fd5b57be34bbcec1955c02e3953fa1d)) ### Bug Fixes - correctly handle new profiles with not allowed upgrades ([5a3d8c1](https://github.com/raydak-labs/configarr/commit/5a3d8c1aa0e6b84808d32ff351cc16fca393664a)), closes [#408](https://github.com/raydak-labs/configarr/issues/408) - **deps:** update dependencies (non-major) ([c3eb357](https://github.com/raydak-labs/configarr/commit/c3eb35730cc02bf1d1f3945789a93b6b84e6890a)) ### (internal) Refactorings - adjust example runs ([8e3ec43](https://github.com/raydak-labs/configarr/commit/8e3ec434e9ee3b451b7757dd42731c3ad1b8e490)) ## [1.23.0](https://github.com/raydak-labs/configarr/compare/v1.22.0...v1.23.0) (2026-02-23) ### Features - add enable merge option ([#394](https://github.com/raydak-labs/configarr/issues/394)) ([97d165d](https://github.com/raydak-labs/configarr/commit/97d165d3dc8af475cc51c4e89d9f5ca8ede831c8)) ## [1.22.0](https://github.com/raydak-labs/configarr/compare/v1.21.0...v1.22.0) (2026-02-20) ### Features - support the breaking changes from TRaSH-Guide. IMPORTANT ([#393](https://github.com/raydak-labs/configarr/issues/393)) ([b2320ea](https://github.com/raydak-labs/configarr/commit/b2320ead2194f9bd0e8268075b582d509bbbb96b)) ## [1.21.0](https://github.com/raydak-labs/configarr/compare/v1.20.0...v1.21.0) (2026-02-17) ### Features - add support for multiple + glob secrets ([69259b1](https://github.com/raydak-labs/configarr/commit/69259b15aa9230c000addea910faab11ad26a30a)) - **config:** Add support for managing UI Config settings ([fd7af46](https://github.com/raydak-labs/configarr/commit/fd7af463058768f89621a8b72e7be15b59ce9628)) ### Bug Fixes - cloning problems when switching urls ([#389](https://github.com/raydak-labs/configarr/issues/389)) ([1cc2c69](https://github.com/raydak-labs/configarr/commit/1cc2c6909116ca8b93b6a842d7abda8ca1792b0c)), closes [#388](https://github.com/raydak-labs/configarr/issues/388) - **deps:** update dependencies (non-major) ([546084b](https://github.com/raydak-labs/configarr/commit/546084bb4238efe621d1364405b311ae57359ce3)) - ignore api key when syncing download clients ([356b141](https://github.com/raydak-labs/configarr/commit/356b14101686f43ba9d66504e7db8c2e6077505c)) ## [1.20.0](https://github.com/raydak-labs/configarr/compare/v1.19.1...v1.20.0) (2026-01-10) ### Features - add Readarr root folder sync support ([8d757de](https://github.com/raydak-labs/configarr/commit/8d757de5d7e4247aebf366f5dc7773d12eda90a3)), closes [raydak-labs/configarr#264](https://github.com/raydak-labs/configarr/issues/264) - add remote path mapping for download clients ([dd7ab2a](https://github.com/raydak-labs/configarr/commit/dd7ab2a3e6138953a850099fd2867059b4358cee)) ### (internal) Refactorings - add generics for better types ([914c2c6](https://github.com/raydak-labs/configarr/commit/914c2c6f14caf9c2ac89b869dcae1226bf90c41c)) - better use client specific things ([042c8e5](https://github.com/raydak-labs/configarr/commit/042c8e528a1909e246c81299b5293ec11da2401c)) - review changes ([0b12b53](https://github.com/raydak-labs/configarr/commit/0b12b5331717b0d8b2a55a628890db7255d36577)) ## [1.19.1](https://github.com/raydak-labs/configarr/compare/v1.19.0...v1.19.1) (2026-01-10) ### Bug Fixes - repair broken changelog links and update release-it plugin ([570b90e](https://github.com/raydak-labs/configarr/commit/570b90e12b3a10e1295446f59456b5fd27d79750)), closes [#355](https://github.com/raydak-labs/configarr/issues/355) - try implementing a fix for legacy kernels in the git checkout process ([778d6ba](https://github.com/raydak-labs/configarr/commit/778d6ba7fe0050ea981bda24a5b634cc1838a756)) ## [1.19.0](https://github.com/raydak-labs/configarr/compare/v1.18.0...v1.19.0) (2025-12-19) ### Features - add download client sync dba819f - Add file tag 9582747 - add support for metadata profiles (lidarr, readarr) 3b7595c - download client general configuration 53fccee ### Bug Fixes - changing remote repos should work without manual intervention f39bac2, closes #359 - correctly handle metadata sync for unrelated services 2cfee60 - **deps:** update dependencies (non-major) ([#355](https://github.com/raydak-labs/configarr/issues/355)) fd70b7b ### (internal) Refactorings - improve error logs a352649 ## [1.18.0](https://github.com/raydak-labs/configarr/compare/v1.17.2...v1.18.0) (2025-11-23) ### Features - add nixos module ([#341](https://github.com/raydak-labs/configarr/issues/341)) ([eabd7a2](https://github.com/raydak-labs/configarr/commit/eabd7a2c2de0151c86edaa76df41de9dce368e19)) - add support for deleting unmanaged quality profiles ([#340](https://github.com/raydak-labs/configarr/issues/340)) ([60bc77d](https://github.com/raydak-labs/configarr/commit/60bc77d00c0c79fbe82f6351ef4a2c01562e631c)) - add support for loading remote templates ([#342](https://github.com/raydak-labs/configarr/issues/342)) ([46ddfc8](https://github.com/raydak-labs/configarr/commit/46ddfc86b9b29c0cdc01ddebc2655aad40fb4ecf)), closes [#301](https://github.com/raydak-labs/configarr/issues/301) ## [1.17.2](https://github.com/raydak-labs/configarr/compare/v1.17.1...v1.17.2) (2025-11-08) ### Bug Fixes - **deps:** update dependencies (non-major) ([#332](https://github.com/raydak-labs/configarr/issues/332)) ([7cbf309](https://github.com/raydak-labs/configarr/commit/7cbf309d951cc3fbb18e0f8b8c0548d1f8a9cd46)) - **deps:** update dependency pino to v10 ([2c2c84c](https://github.com/raydak-labs/configarr/commit/2c2c84c09bba48ef58e2e531d4a72d7f9a59915e)) - **deps:** update dependency zod to v4 ([73be722](https://github.com/raydak-labs/configarr/commit/73be722186fd42c014561c99de312b486f94e229)) - **deps:** update docusaurus monorepo to v3.9.2 ([#329](https://github.com/raydak-labs/configarr/issues/329)) ([d7a1276](https://github.com/raydak-labs/configarr/commit/d7a1276e87f3d0a2c6ccd5623b7cc422545cd36c)) - root folder for lidarr sync ([6c67999](https://github.com/raydak-labs/configarr/commit/6c67999b54cdd32c4bd119f5818cf227fcaa7eb3)) - windows binary builds ([dfc2982](https://github.com/raydak-labs/configarr/commit/dfc2982af10111d6e167bfeb3c6bb680148854d4)) ### (internal) Refactorings - restructure rootFolder code ([2f5b83d](https://github.com/raydak-labs/configarr/commit/2f5b83dd11e14ff85868b0c964d368212990a82a)) ## [1.17.1](https://github.com/raydak-labs/configarr/compare/v1.17.0...v1.17.1) (2025-10-10) ### Bug Fixes - binary variables ([a35408c](https://github.com/raydak-labs/configarr/commit/a35408c9b96c9cd6c7b863ef2c156a8aacbc9dc1)) ## [1.17.0](https://github.com/raydak-labs/configarr/compare/v1.16.0...v1.17.0) (2025-10-09) ### Features - add configarr binary ([bd8819b](https://github.com/raydak-labs/configarr/commit/bd8819b54d41778a5b52323edfc476719657d009)), closes [#272](https://github.com/raydak-labs/configarr/issues/272) ### Bug Fixes - **deps:** update dependencies (non-major) ([#314](https://github.com/raydak-labs/configarr/issues/314)) ([5afcd36](https://github.com/raydak-labs/configarr/commit/5afcd36c3ce5091fc10d078bb05a982008f580ab)) - **deps:** update docusaurus monorepo to v3.9.1 ([1b0a4b2](https://github.com/raydak-labs/configarr/commit/1b0a4b2fa2c7e9b5651af2e0931ba9fec360ed2b)) ## [1.16.0](https://github.com/raydak-labs/configarr/compare/v1.15.1...v1.16.0) (2025-09-27) ### Features - add possibity to add custom formats without assign to profile ([88b78ca](https://github.com/raydak-labs/configarr/commit/88b78ca1c1dddeb604a6348d4589491475b72b12)), closes [#279](https://github.com/raydak-labs/configarr/issues/279) - add telemetry - default disabled ([a0fc6d0](https://github.com/raydak-labs/configarr/commit/a0fc6d08b97b147ab168e77ade8f9a4375c0f12c)) - implement score for custom format groups closes [#196](https://github.com/raydak-labs/configarr/issues/196) ([2933d0f](https://github.com/raydak-labs/configarr/commit/2933d0f011ff12eb8b8f15952e8df7824110913f)) ## [1.15.1](https://github.com/raydak-labs/configarr/compare/v1.15.0...v1.15.1) (2025-09-04) ### Bug Fixes - recursively load all recyclarr templates and not only first level of directory ([374b767](https://github.com/raydak-labs/configarr/commit/374b767a470530b91561725e272a22fd15b3ff15)), closes [#305](https://github.com/raydak-labs/configarr/issues/305) ## [1.15.0](https://github.com/raydak-labs/configarr/compare/v1.14.1...v1.15.0) (2025-08-27) ### Features - include all relevant CF-Groups (and marked CFs) for TRaSH-Guide profiles automatically ([065de47](https://github.com/raydak-labs/configarr/commit/065de471e4d2feecd198dcc33753933e216b9284)), closes [/github.com/TRaSH-Guides/Guides/pull/2455#discussion_r2297832409](https://github.com/raydak-labs//github.com/TRaSH-Guides/Guides/pull/2455/issues/discussion_r2297832409) ## [1.14.1](https://github.com/raydak-labs/configarr/compare/v1.14.0...v1.14.1) (2025-08-13) ### Bug Fixes - correctly handle group cfs in mix with cfs ([8974eac](https://github.com/raydak-labs/configarr/commit/8974eac26b213c5ea3a1a437765b92fb2831bedc)), closes [#289](https://github.com/raydak-labs/configarr/issues/289) ## [1.14.0](https://github.com/raydak-labs/configarr/compare/v1.13.7...v1.14.0) (2025-08-04) ### Features - add support for root folders ([9e717ff](https://github.com/raydak-labs/configarr/commit/9e717ff25184bec830dbec5fad0faab346f73c21)), closes [#264](https://github.com/raydak-labs/configarr/issues/264) - implement delay profiles ([19c7bbe](https://github.com/raydak-labs/configarr/commit/19c7bbe5d65148393ddeaad37d33d21fd5010c0f)) ### Bug Fixes - **deps:** update dependencies (non-major) ([#292](https://github.com/raydak-labs/configarr/issues/292)) ([3c46cd7](https://github.com/raydak-labs/configarr/commit/3c46cd7166cafb85ef3019400f43851feadc52a6)) ### (internal) Refactorings - update generated api ([b188e8b](https://github.com/raydak-labs/configarr/commit/b188e8b1e307001795eab6610944e9ffd8f021e0)) ## [1.13.7](https://github.com/raydak-labs/configarr/compare/v1.13.6...v1.13.7) (2025-07-22) ### Bug Fixes - do not delete CFs when dry run enabled fixes [#290](https://github.com/raydak-labs/configarr/issues/290) ([cff234b](https://github.com/raydak-labs/configarr/commit/cff234be81fe5dc576ee0be1f21eb45442a5cf45)) ## [1.13.6](https://github.com/raydak-labs/configarr/compare/v1.13.5...v1.13.6) (2025-07-09) ### Bug Fixes - correctly lookup quality definition names from quality profiles fix [#281](https://github.com/raydak-labs/configarr/issues/281) ([728cbde](https://github.com/raydak-labs/configarr/commit/728cbde67f2da82805934286f0aa69ba9bbfd85b)) - **deps:** update dependencies (non-major) ([dbe405a](https://github.com/raydak-labs/configarr/commit/dbe405a9773e0c199ab87dd18160b2c44456bdce)) ## [1.13.5](https://github.com/raydak-labs/configarr/compare/v1.13.4...v1.13.5) (2025-05-03) ### Bug Fixes - correctly handle possible empty quality arrays ([1ac9912](https://github.com/raydak-labs/configarr/commit/1ac9912f6af01c20604f04a5d795648104fcb80f)) - correctly order qualities in groups of a profile ([c27b703](https://github.com/raydak-labs/configarr/commit/c27b7031eca10bcd3b09e39f72fb774f3a9bcf0f)) - **deps:** update dependencies (non-major) ([#257](https://github.com/raydak-labs/configarr/issues/257)) ([27387bb](https://github.com/raydak-labs/configarr/commit/27387bbf07be44fe9d98569693bbec5ab18f9581)) - improve check for ordering of qualities ([d9ac0ee](https://github.com/raydak-labs/configarr/commit/d9ac0ee21d8f0dd6d85cfa4080fdd86d10b3f5a4)) - reverse qualities in groups from trash guide ([83479e7](https://github.com/raydak-labs/configarr/commit/83479e771bf4a23175e698eaa64b9f31f962fed8)) ### (internal) Refactorings - remove unnecessary qualities check ([d55c0ec](https://github.com/raydak-labs/configarr/commit/d55c0ec7893b61ec69531285ffd941d05fc5a6a5)) - simplify starting code ([b969526](https://github.com/raydak-labs/configarr/commit/b9695265801e5fe5e7c3978cd1c10f6118afedcd)) ## [1.13.4](https://github.com/raydak-labs/configarr/compare/v1.13.3...v1.13.4) (2025-04-12) ### Bug Fixes - correctly import quality size / definitions from trash github ([1e2099d](https://github.com/raydak-labs/configarr/commit/1e2099d49a7f044f66dc67fc4f1c178b082dac0f)) - safe directory, see [#241](https://github.com/raydak-labs/configarr/issues/241) ([d1c237b](https://github.com/raydak-labs/configarr/commit/d1c237b2acbadce8c525d882a5a906cdb1318e68)) ## [1.13.3](https://github.com/raydak-labs/configarr/compare/v1.13.2...v1.13.3) (2025-04-03) ### Bug Fixes - allow all users to access git directory. ([#241](https://github.com/raydak-labs/configarr/issues/241)) ([a9b59da](https://github.com/raydak-labs/configarr/commit/a9b59dac61600963f66c87da8a2544da8dcae1dc)), closes [#240](https://github.com/raydak-labs/configarr/issues/240) - **deps:** update dependencies (non-major) ([#238](https://github.com/raydak-labs/configarr/issues/238)) ([5fe6270](https://github.com/raydak-labs/configarr/commit/5fe627082873ca4bdf88e8d494ca4cacdf6d87d9)) ## [1.13.2](https://github.com/raydak-labs/configarr/compare/v1.13.1...v1.13.2) (2025-03-23) ### Bug Fixes - do not fail empty QualityProfiles or CustomFormats are received from server ([d78b441](https://github.com/raydak-labs/configarr/commit/d78b44116aeca689b6543859e711da4b36a8257a)), closes [#230](https://github.com/raydak-labs/configarr/issues/230) ## [1.13.1](https://github.com/raydak-labs/configarr/compare/v1.13.0...v1.13.1) (2025-03-10) ### Bug Fixes - improve cloning of quality_profiles configs ([89af504](https://github.com/raydak-labs/configarr/commit/89af504f380bc7c21df2ce48a3a8f3748bae23cc)), closes [#223](https://github.com/raydak-labs/configarr/issues/223) ## [1.13.0](https://github.com/raydak-labs/configarr/compare/v1.12.2...v1.13.0) (2025-03-05) ### Features - support mapping custom formats on unmanaged quality profiles ([cd6dea6](https://github.com/raydak-labs/configarr/commit/cd6dea67c5a7835e68b26255a7f451c73d74720e)), closes [#218](https://github.com/raydak-labs/configarr/issues/218) ### Bug Fixes - **deps:** update dependencies (non-major) ([#208](https://github.com/raydak-labs/configarr/issues/208)) ([dbe40d1](https://github.com/raydak-labs/configarr/commit/dbe40d12dd7fe5a9a07581f5047a7920640cc8f0)) ### (internal) Refactorings - fix incorrect path in log message ([#215](https://github.com/raydak-labs/configarr/issues/215)) ([ebec0a1](https://github.com/raydak-labs/configarr/commit/ebec0a1a88ed19576a24bdedbabc1f48f8bd5249)) - fix typo (closes [#202](https://github.com/raydak-labs/configarr/issues/202)) ([1bad256](https://github.com/raydak-labs/configarr/commit/1bad256ffe13bb75431d8175094723bc09ef59f5)) ## [1.12.2](https://github.com/raydak-labs/configarr/compare/v1.12.1...v1.12.2) (2025-02-27) ### Bug Fixes - correctly merge templates and configs ([9235c47](https://github.com/raydak-labs/configarr/commit/9235c47923e3a81da081e73596d018b7c987e9d0)) ### (internal) Refactorings - improve logging for customformatgroups ([f8560df](https://github.com/raydak-labs/configarr/commit/f8560df015b3ee60393461fab3ebd5cacbcff124)) ## [1.12.1](https://github.com/raydak-labs/configarr/compare/v1.12.0...v1.12.1) (2025-02-19) ### (internal) Refactorings - **deps:** update node and pnpm ([8574d3b](https://github.com/raydak-labs/configarr/commit/8574d3b4fb380d3fbbad7bf31a0f90809f0534f6)) - improve logs ([d611c0e](https://github.com/raydak-labs/configarr/commit/d611c0e40d8166b188904f34cb19c7e1f8831860)), closes [#197](https://github.com/raydak-labs/configarr/issues/197) ## [1.12.0](https://github.com/raydak-labs/configarr/compare/v1.11.0...v1.12.0) (2025-02-10) ### Features - add support for cleaning up custom formats ([7a28d54](https://github.com/raydak-labs/configarr/commit/7a28d54f678d9231642c02d12c0df58ee97786dd)), closes [#191](https://github.com/raydak-labs/configarr/issues/191) - add support for trash custom format groups ([c307377](https://github.com/raydak-labs/configarr/commit/c30737781a3ce47ddd6dafcc978fddcb33137d41)), closes [#185](https://github.com/raydak-labs/configarr/issues/185) ## [1.11.0](https://github.com/raydak-labs/configarr/compare/v1.10.3...v1.11.0) (2025-02-05) ### Features - add option to disable specific instances in config ([e228ccb](https://github.com/raydak-labs/configarr/commit/e228ccb0820cdb54daf1608280f2a3e0f1304113)), closes [#184](https://github.com/raydak-labs/configarr/issues/184) ### Bug Fixes - do gracefully stop instance processing if an error occurs. ([8f8fca5](https://github.com/raydak-labs/configarr/commit/8f8fca5013d5abec15b35accf568b44abc17027d)) ### (internal) Refactorings - log total execution summary ([35d0c30](https://github.com/raydak-labs/configarr/commit/35d0c3049c2696a940147468c187380b08274d6f)) ## [1.10.3](https://github.com/raydak-labs/configarr/compare/v1.10.2...v1.10.3) (2025-02-03) ### Bug Fixes - correctly set language for new QualityProfiles ([9ab962b](https://github.com/raydak-labs/configarr/commit/9ab962bd469bb838ba7158594f1f841120890cdb)), closes [#180](https://github.com/raydak-labs/configarr/issues/180) - **deps:** pin dependency raw-loader to 4.0.2 ([#171](https://github.com/raydak-labs/configarr/issues/171)) ([1fd8d46](https://github.com/raydak-labs/configarr/commit/1fd8d460f0d331970bc70d53eeac2830be7074d7)) - **deps:** update dependency docusaurus-lunr-search to v3.6.0 ([#175](https://github.com/raydak-labs/configarr/issues/175)) ([1afcaa2](https://github.com/raydak-labs/configarr/commit/1afcaa2428590509ee94fc8c0d80bd13c3cccb6c)) ## [1.10.2](https://github.com/raydak-labs/configarr/compare/v1.10.1...v1.10.2) (2025-01-23) ## [1.10.1](https://github.com/raydak-labs/configarr/compare/v1.10.0...v1.10.1) (2025-01-21) ### Bug Fixes - use new cfs in existin g qps correctly ([d24aaa6](https://github.com/raydak-labs/configarr/commit/d24aaa6cfc97806a932389f12d41ae4cecc17719)), closes [#164](https://github.com/raydak-labs/configarr/issues/164) ## [1.10.0](https://github.com/raydak-labs/configarr/compare/v1.9.0...v1.10.0) (2025-01-19) ### Features - add experimental support for cloning quality profiles ([18941ec](https://github.com/raydak-labs/configarr/commit/18941ec259832f291474e5f140fb3f525ed5872c)) - add experimental support for quality profiles renaming ([504dfe3](https://github.com/raydak-labs/configarr/commit/504dfe3ff4de7df841878d9bf6524201d335ec46)) ## [1.9.0](https://github.com/raydak-labs/configarr/compare/v1.8.0...v1.9.0) (2025-01-15) ### Features - allow configuring quality sizes / definitions with config and templates (alpha) ([f41891b](https://github.com/raydak-labs/configarr/commit/f41891bd87b877cc3c292c737d0dca8e060932d8)), closes [#140](https://github.com/raydak-labs/configarr/issues/140) ### (internal) Refactorings - ensure all quality definitions always exist if updated ([6aa37cd](https://github.com/raydak-labs/configarr/commit/6aa37cd9eafa6dfa748462508d7c1b0d9679ce0a)) - ignore empty local templates ([1454670](https://github.com/raydak-labs/configarr/commit/145467033c2282078a41cce98322819032ce340b)) - restructure trash QD preferred scaling ([53da038](https://github.com/raydak-labs/configarr/commit/53da0381ce928aa743f7f2655b00fc9b40c5349f)) ## [1.8.0](https://github.com/raydak-labs/configarr/compare/v1.7.0...v1.8.0) (2025-01-13) ### Features - add experimental lidarr support ([2093ae0](https://github.com/raydak-labs/configarr/commit/2093ae0fc3fc49b3bb3d77042d33f1ddd45036e4)) ### Bug Fixes - handle local templates as recyclarr templates correctly ([10d7bdb](https://github.com/raydak-labs/configarr/commit/10d7bdb1622ed7b3adbb06bda7d048f113ce24dd)) ## [1.7.0](https://github.com/raydak-labs/configarr/compare/v1.6.0...v1.7.0) (2025-01-13) ### Features - use language from TrashQPs ([7e8981b](https://github.com/raydak-labs/configarr/commit/7e8981b54d5296e1dc9830e4ab7342a948c66fc0)) ### (internal) Refactorings - only build update object for objects with keys ([7abe91c](https://github.com/raydak-labs/configarr/commit/7abe91cb9438fb43ff16d92edb1ae7d2e8693e39)) ## [1.6.0](https://github.com/raydak-labs/configarr/compare/v1.5.3...v1.6.0) (2025-01-10) ### Features - add media_naming compatibility from recyclarr ([3cf73dc](https://github.com/raydak-labs/configarr/commit/3cf73dc2cbbff6fabd1b6e82a9b5b813a307ef26)) ### Bug Fixes - adjust qualityprofile items to always include items key ([9ed86b3](https://github.com/raydak-labs/configarr/commit/9ed86b306c1e8c26bbc4a8c466acf3c84f0240d3)) - correct customFormatDefinition loading from top level ([f841617](https://github.com/raydak-labs/configarr/commit/f841617c282d0426625824a7b36939df688854ce)) ### (internal) Refactorings - create trash cache for optimization ([d142fee](https://github.com/raydak-labs/configarr/commit/d142feeda4dcccc0649d4c0ce2d65836d23640bc)) - improve types ([f44eb35](https://github.com/raydak-labs/configarr/commit/f44eb3521401ef44943b71e0921c52e97a3ca2d9)) ## [1.5.3](https://github.com/raydak-labs/configarr/compare/v1.5.2...v1.5.3) (2025-01-08) ### Bug Fixes - allow loading custom format definition correctly from templates ([a5f0f92](https://github.com/raydak-labs/configarr/commit/a5f0f9211b6eac001b9467476aab2a19c93ec6aa)) ### (internal) Refactorings - make CF loading cleaner ([5b33849](https://github.com/raydak-labs/configarr/commit/5b33849e8d30d53e38c2503c33d319035d02b9a0)) - move merge config to config.ts ([388875d](https://github.com/raydak-labs/configarr/commit/388875dd2240866b071df67d3560e5d461bc2bb7)) ## [1.5.2](https://github.com/raydak-labs/configarr/compare/v1.5.1...v1.5.2) (2025-01-03) ### Bug Fixes - correctly set preferred size value if adjusted by ratio ([5d9dc5c](https://github.com/raydak-labs/configarr/commit/5d9dc5c652f9288063391bb5317f31ad2a9d50dc)) - **deps:** pin dependency zod to 3.24.1 ([#133](https://github.com/raydak-labs/configarr/issues/133)) ([3773dde](https://github.com/raydak-labs/configarr/commit/3773ddeb7ffecb7bc979d5fa27f6f091f983e983)) - **deps:** update dependencies (non-major) ([#135](https://github.com/raydak-labs/configarr/issues/135)) ([3ac7b7c](https://github.com/raydak-labs/configarr/commit/3ac7b7c5cad63ac3acc99a3cd95fe3c9854634f6)) - **deps:** update react monorepo to v19 ([c57a95b](https://github.com/raydak-labs/configarr/commit/c57a95b2394875843d2554d4a1fb910ca32a96be)) - use quality_defintion from main config if defined ([94d1861](https://github.com/raydak-labs/configarr/commit/94d186160832a2249dfa7626d532a690d91ea72a)) ### (internal) Refactorings - rename variables in code only ([f2f3736](https://github.com/raydak-labs/configarr/commit/f2f37362153bbc09b8633f710b506ed5d26d9db5)) ## [1.5.1](https://github.com/raydak-labs/configarr/compare/v1.5.0...v1.5.1) (2024-12-29) ### Bug Fixes - correctly handle diffs for minFormatScores ([a2494db](https://github.com/raydak-labs/configarr/commit/a2494db839f283d9b0b16b18584b7b745af65e20)) ## [1.5.0](https://github.com/raydak-labs/configarr/compare/v1.4.0...v1.5.0) (2024-12-17) ### Features - add configuration options for media management tab ([c2f2110](https://github.com/raydak-labs/configarr/commit/c2f2110f58f05cd7400ad12f0dc7bf77b0343d3c)) - add support for loading customformat definitions ([4014d93](https://github.com/raydak-labs/configarr/commit/4014d938f5ab4b747be90c5a65e180941a3dcbdb)) - optimize envs and add support for custom root for data [#117](https://github.com/raydak-labs/configarr/issues/117) ([f218b56](https://github.com/raydak-labs/configarr/commit/f218b56cf6b43e0508efa1f061223c264985bc1e)) ### Bug Fixes - **deps:** pin dependencies ([#118](https://github.com/raydak-labs/configarr/issues/118)) ([912130a](https://github.com/raydak-labs/configarr/commit/912130a347ff7e06f012778c87a72db20e8aee2b)) - **deps:** update dependencies (non-major) ([a181831](https://github.com/raydak-labs/configarr/commit/a181831ad10b30b945683a1d0f005a6ed54d64c7)) - **deps:** update dependency pino-pretty to v13 ([c05c07f](https://github.com/raydak-labs/configarr/commit/c05c07f1241c0c0f47f916071b9c426883b2117e)) - set default language for new profiles to any ([ffd6faa](https://github.com/raydak-labs/configarr/commit/ffd6faae718df8e13e520db8bf7d4525bcc31d5b)) ### (internal) Refactorings - improve typings for client ([b9ad772](https://github.com/raydak-labs/configarr/commit/b9ad772418fd041f72fd9432d89bb2adf54b083b)) ## [1.4.0](https://github.com/raydak-labs/configarr/compare/v1.3.0...v1.4.0) (2024-11-17) ### Features - add experimental support for readarr ([9085a52](https://github.com/raydak-labs/configarr/commit/9085a5248199bc710187f0a9a8a4c46df43f5083)) - add expermintal whisparr v3 support ([ff2f08e](https://github.com/raydak-labs/configarr/commit/ff2f08ea551bbd1e57322a82c6705168ac256e73)) - implement preferredRatio ([b6333db](https://github.com/raydak-labs/configarr/commit/b6333db1a14a4ac68da3c74e43ac9a1a2a15179f)) - make Trash template / QualityProfiles includable ([5339ced](https://github.com/raydak-labs/configarr/commit/5339ced26ee4f5596f23a10cc93e8879efddc9e6)) ### Bug Fixes - **deps:** update dependencies (non-major) ([cd8b081](https://github.com/raydak-labs/configarr/commit/cd8b081b1432ddbc4f0695859335bee0e33760b1)) ### (internal) Refactorings - adjust some logging ([795ecbd](https://github.com/raydak-labs/configarr/commit/795ecbd2baf9dfbd0a448763b74e838d01c8c904)) - fix test ([bcfa622](https://github.com/raydak-labs/configarr/commit/bcfa62289913d1ce96a9c1ec675278e80f99e461)) - improve flow ([738949a](https://github.com/raydak-labs/configarr/commit/738949ae2df841742585a93a510b3c5849623972)) - improve ky error log ([e68e073](https://github.com/raydak-labs/configarr/commit/e68e073d986e387d362b8826e5d526f97515c35d)) - move index.ts to src ([b6052e5](https://github.com/raydak-labs/configarr/commit/b6052e5669ac21368635a670fe8e06e7e6c71f07)) - move types ([98aa2fe](https://github.com/raydak-labs/configarr/commit/98aa2feef8ed0f2579fffeb46c8262e33431c25f)) - remove tsconfig paths config ([4a34869](https://github.com/raydak-labs/configarr/commit/4a34869e6ba4f25f22180ce20606d7734e55e5a3)) - rewrite api client usage ([43784ba](https://github.com/raydak-labs/configarr/commit/43784ba3988b9dafb1a65fd63d1b2cc16c8650d9)) - split config merging and improve types ([2aa101c](https://github.com/raydak-labs/configarr/commit/2aa101cb3f16c70473c4469423eaf97f0425a18c)) - split local path importer ([e0871ac](https://github.com/raydak-labs/configarr/commit/e0871ac9443007f3bf3f8011870c1f0413022715)) - unify clone repo ([18c1b69](https://github.com/raydak-labs/configarr/commit/18c1b69b8571dd4dcd7d7973e65fe36a31c403d0)) - update sonarr/radarr apis ([1dc0d09](https://github.com/raydak-labs/configarr/commit/1dc0d094a0533d61cc078b901b0307602632ddf0)) - use configureApi ([27aed23](https://github.com/raydak-labs/configarr/commit/27aed239c93b9aab7c5cae773c821f3819b27075)) ================================================ FILE: CNAME ================================================ configarr.raydak.de configarr.de ================================================ FILE: DEV.md ================================================ # Development related README ## Compiling to binary ### bun (trying) - compiles and treeshakes code already - `bun build src/index.ts --compile --outfile cli-bun` - size: 61mb ```bash # what could be done but now sure if any real benefit bun build src/index.ts \ --compile \ --outfile configarr-${{ matrix.platform }} \ --define CONFIGARR_VERSION=\"${{ steps.vars.outputs.version }}\" \ --define BUILD_TIME=\"${{ steps.vars.outputs.build_time }}\" \ --define GITHUB_RUN_ID=\"${{ steps.vars.outputs.run_id }}\" \ --define GITHUB_REPO=\"${{ steps.vars.outputs.repo }}\" \ --define GITHUB_SHA=\"${{ steps.vars.outputs.sha }}\" \ --define BUILD_PLATFORM=\"${{ matrix.platform }}\" \ --bytecode \ --production \ --minify \ --minify-syntax \ --minify-whitespace \ --minify-identifiers \ ${{ github.event.inputs.baseline == 'true' && '--target=bun' || '' }} ``` ### deno - `pnpm build` - `deno compile --no-check --sloppy-imports --output cli-deno --no-npm --allow-all bundle.cjs` - size: 77mb ## docker - we could probably just use scratch as base? with the binary? ================================================ FILE: Dockerfile ================================================ # https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md # TODO because multiarch build has problems with QEMU and Node we cannot use alpine here: https://github.com/nodejs/docker-node/issues/1798 FROM node:24.14.1-slim AS base WORKDIR /app ENV PNPM_HOME="/opt/pnpm" ENV COREPACK_HOME="/opt/corepack" ENV PATH="$PNPM_HOME:$PATH" ENV CI=true RUN apt-get update && apt-get install -y \ git \ && rm -rf /var/lib/apt/lists/* COPY package.json pnpm-lock.yaml ./ # Do it here to add the packageManager field to the package.json RUN corepack enable \ && corepack prepare pnpm@10 --activate \ && corepack use pnpm@10 RUN pnpm config set store-dir ~/.pnpm-store RUN --mount=type=cache,id=pnpm,target=~/.pnpm-store pnpm install --frozen-lockfile FROM base AS builder COPY src src/ COPY esbuild.ts ./ ARG CONFIGARR_VERSION=dev ARG BUILD_TIME="" ARG GITHUB_RUN_ID="" ARG GITHUB_REPO="" ARG GITHUB_SHA="" ENV CONFIGARR_VERSION=${CONFIGARR_VERSION} ENV BUILD_TIME=${BUILD_TIME} ENV GITHUB_RUN_ID=${GITHUB_RUN_ID} ENV GITHUB_REPO=${GITHUB_REPO} ENV GITHUB_SHA=${GITHUB_SHA} RUN pnpm run build FROM base AS dev # manually mount src etc ARG CONFIGARR_VERSION=dev ENV CONFIGARR_VERSION=${CONFIGARR_VERSION} CMD [ "pnpm", "start" ] # https://github.com/evanw/esbuild/issues/1921 FROM node:24.14.1-alpine AS prod WORKDIR /app RUN apk add --no-cache libstdc++ dumb-init git # Allow global git access independent of container user and directory user. See #240, #241 RUN git config --global --add safe.directory '*' # TODO maybe in future. Results in breaking change #USER node COPY --from=builder /app/bundle.cjs /app/index.js ARG CONFIGARR_VERSION=dev ENV CONFIGARR_VERSION=${CONFIGARR_VERSION} # Run with dumb-init to not start node with PID=1, since Node.js was not designed to run as PID 1 CMD ["dumb-init", "node", "index.js"] # Compatibility target pinned to Alpine 3.22. # Useful for testing old-kernel behavior with a fixed Alpine/git stack. FROM node:24.14.1-alpine3.22 AS prod-alpine-3-22 WORKDIR /app RUN apk add --no-cache libstdc++ dumb-init git # Allow global git access independent of container user and directory user. See #240, #241 RUN git config --global --add safe.directory '*' COPY --from=builder /app/bundle.cjs /app/index.js ARG CONFIGARR_VERSION=dev ENV CONFIGARR_VERSION=${CONFIGARR_VERSION} CMD ["dumb-init", "node", "index.js"] ================================================ FILE: Dockerfile-deno.Dockerfile ================================================ # https://github.com/denoland/deno_docker/blob/main/example/Dockerfile FROM denoland/deno:alpine-2.0.0 AS base WORKDIR /app RUN apk add --no-cache libstdc++ dumb-init git COPY package.json pnpm-lock.yaml ./ RUN deno install FROM base AS builder COPY src src/ COPY index.ts esbuild.ts ./ RUN deno --allow-env --allow-read --allow-run esbuild.ts FROM base AS dev ENV DENO_DIR=/app/.deno_cache # manually mount src etc CMD ["deno", "--allow-env", "--allow-read", "--allow-run", "--allow-net", "--allow-sys", "--unstable-sloppy-imports", "index.ts"] # https://github.com/evanw/esbuild/issues/1921 FROM denoland/deno:alpine-2.0.0 AS prod WORKDIR /app RUN apk add --no-cache libstdc++ dumb-init git # TODO maybe in future. Results in breaking change #USER node COPY --from=builder /app/bundle.cjs /app/index.cjs ENV DENO_DIR=/app/.deno_cache # Compile cache / modify for multi-user RUN deno cache --unstable-sloppy-imports index.cjs || true RUN chmod uga+rw -R ${DENO_DIR} # Not sure about those options #--cached-only #--no-code-cache # TODO not sure about this # Run with dumb-init to not start node with PID=1, since Node.js was not designed to run as PID 1 CMD ["dumb-init", "deno", "--allow-env", "--allow-read", "--allow-run", "--allow-net", "--allow-sys", "--unstable-sloppy-imports", "index.cjs"] # BUN Sample # FROM oven/bun:1.1.30-alpine AS prod # WORKDIR /app # RUN apk add --no-cache libstdc++ dumb-init git # # TODO maybe in future. Results in breaking change # #USER node # COPY --from=builder /app/bundle.cjs /app/index.cjs # ENV CONFIG_LOCATION=/app/config/config.yml # ENV SECRETS_LOCATION=/app/config/secrets.yml # # Run with dumb-init to not start node with PID=1, since Node.js was not designed to run as PID 1 # CMD ["dumb-init", "bun", "index.cjs"] ================================================ FILE: GEMINI.md ================================================ ## General You are a TypeScript expert specializing in modern TS and async programming. ## Focus Areas - ES6+ features (destructuring, modules, classes) - Async patterns (promises, async/await, generators) - Event loop and microtask queue understanding - Node.js APIs and performance optimization - Browser APIs and cross-browser compatibility - TypeScript migration and type safety ## Approach 1. Prefer async/await over promise chains 2. Use functional patterns where appropriate 3. Handle errors at appropriate boundaries 4. Avoid callback hell with modern patterns 5. Consider bundle size for browser code 6. Try adding types where needed. Avoid using any. ## Output - Modern TypeScript with proper error handling - Async code with race condition prevention - Module structure with clean exports - Jest tests with async test patterns ## Project IMPORTANT - source code is located in `src` - This is a software for synching external tools: `sonarr, radarr, ...` with a unified configuration - Sample confguration file is here `examples/full/config/config.yml` - The external api endpoint are automatically generated and stored here `src/__generated__` (only look into it when required) - A merged configuration per client is here `src/clients` - After you are done run `pnpm lint:fix` - In the end the following commands should run without error: - `pnpm build` - `pnpm lint` - `pnpm typecheck` - `pnpm test` ## Useful Command-Line Tools - `jq` for interacting with json - `rg` (ripgrep) command is available for fast searches in text files. - `fzf` for fuzzy finding - `git` for interacting with git repos - `fd` for faster finds ## Regarding Dependencies: - Avoid introducing new external dependencies unless absolutely necessary. - If a new dependency is required, please state the reason. ================================================ FILE: LICENSE ================================================ GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software. A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public. The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version. An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU Affero General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Remote Network Interaction; Use with the GNU General Public License. Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see . ================================================ FILE: README.md ================================================ # Configarr [![Documentation](https://img.shields.io/badge/Documentation-blue)](https://configarr.de) [![GitHub License](https://img.shields.io/github/license/raydak-labs/configarr)](https://github.com/raydak-labs/configarr/blob/main/LICENSE) [![GitHub Release](https://img.shields.io/github/v/release/raydak-labs/configarr?logo=github)](https://github.com/raydak-labs/configarr/releases/) [![Docker](https://img.shields.io/docker/v/configarr/configarr?sort=semver&label=DockerHub)](https://hub.docker.com/r/configarr/configarr) [![Docker Pulls](https://img.shields.io/docker/pulls/configarr/configarr?label=DockerHub-Pulls)](https://hub.docker.com/r/configarr/configarr)

Logo of configarr

Configarr is an open-source tool designed to simplify configuration and synchronization for Sonarr and Radarr (and other experimental). It integrates with TRaSH Guides to automate updates of custom formats, quality profiles, and other settings, while also supporting user-defined configurations. Configarr offers flexibility with deployment options like Docker and Kubernetes, ensuring compatibility with the latest versions of Sonarr and Radarr. By streamlining media server management, it saves time, enhances consistency, and reduces manual intervention. Official support only for Sonarr v4 and radarr v5. This will be a project similar to [Recyclarr](https://github.com/recyclarr/recyclarr) or [Notifiarr](https://notifiarr.wiki/) but support for additional specification and not only what [TRaSH-Guides](https://trash-guides.info/) offer. ## Container Images Images are available via Github Container Registry (ghcr) and dockerhub with tags and latest (check the repos for all available tags): - [GHCR:](https://github.com/raydak-labs/configarr/pkgs/container/configarr) - `ghcr.io/raydak-labs/configarr:latest` - [DockerHub:](https://hub.docker.com/repository/docker/configarr/configarr/general) - `docker.io/configarr/configarr:latest` or simply `configarr/configarr:latest` ## Features - Use TRaSH-Guides defined custom formats - Compatible with recyclarr templates - Include own defined custom formats - Custom defined formats for different languages/countries like Germany - Support all CustomFormat specifications - Provide CFs in different ways - Sync from TRaSH-Guides - Sync with local file CFs - Provide CFs directly in config (Convert JSON with https://www.bairesdev.com/tools/json2yaml/) - Merge order is `TRaSH-Guides -> LocalFiles -> CFs in Config` ### Supported \*arr Applications - Radarr v5 - Sonarr v4 - Whisparr (experimental) - Readarr (experimental) - Lidarr (experimental) ## Configuration Full documentation can be found here: [Documentation](https://configarr.de) - `config.yml` - Check the template file [template](./config.yml.template) or check the examples. - You can provide values with the custom tags: - `value: !secret secretKey`: Loads the value from the secrets file with the key `secretKey` - `value: !env ENV_NAME`: Loads the value from the environment variable `ENV_NAME` - `value: !file FILE_NAME`: Loads the value from the file `FILE_NAME` - Make sure Configarr has enough permissions to read the file ## Custom formats This repository also provide additional custom formats what TRaSH-Guides does not offer. See [here](./custom/cfs/) - Most CustomFormats used from @PCJones - See here: https://github.com/PCJones/radarr-sonarr-german-dual-language - Or good german guide: https://github.com/PCJones/usenet-guide ## Development 1. Optionally setup the local sonarr instance 1. Run `docker compose up -d` to run the container 2. Open sonarr in your browser at http://localhost:8989 / radarr @ http://localhost:7878 3. Configure basic authentication, disable local authentication and create an initial user by specifying the e-mail and password 2. Open the sonarr [Settings > General](http://localhost:8989/settings/general) page and copy the API key 3. Create a `secrets.yml` from the template 1. `cp secrets.yml.template secrets.yml` 2. Replace the placeholder with your sonarr API key 4. Create a `config.yml` from the template 1. `cp config.yml.template config.yml` 2. Overwrite the hosts in case you are not using the local setup with docker compose 5. Run the app with `pnpm start` or with the vscode task Tip: Beside from those steps you can also always test and work with the `full example` and utilizing the docker container with mounted `src` directory. ## Examples Some examples for configuration are provided [Examples](./examples/) ## Related projects You can compare features here: [Feature Comparison](https://configarr.de/docs/comparison) - https://github.com/recyclarr/recyclarr - https://notifiarr.wiki/ - https://github.com/Dictionarry-Hub/profilarr ## Star History [![Star History Chart](https://api.star-history.com/svg?repos=raydak-labs/configarr&type=Date)](https://www.star-history.com/#raydak-labs/configarr&Date) ================================================ FILE: config.yml.template ================================================ trashGuideUrl: https://github.com/TRaSH-Guides/Guides #trashRevision: master # Optional to specify sha recyclarrConfigUrl: https://github.com/recyclarr/config-templates #recyclarrRevision: master # Optional to specify sha # Optional if you want to add custom formats locally #localCustomFormatsPath: ./custom/cfs #localConfigTemplatesPath: /app/templates sonarr: series: # Set the URL/API Key to your actual instance base_url: http://localhost:8989 api_key: !secret SONARR_API_KEY # Quality definitions from the guide to sync to Sonarr. Choices: series, anime quality_definition: type: series include: # Comment out any of the following includes to disable them #### WEB-1080p - template: sonarr-quality-definition-series - template: sonarr-v4-quality-profile-web-1080p - template: sonarr-v4-custom-formats-web-1080p #### WEB-2160p - template: sonarr-v4-quality-profile-web-2160p - template: sonarr-v4-custom-formats-web-2160p # Custom Formats: https://recyclarr.dev/wiki/yaml/config-reference/custom-formats/ custom_formats: [] radarr: instance1: define: true ================================================ FILE: custom/cfs/custom-size-bigger-40gb.json ================================================ { "trash_id": "custom-size-more-40gb", "trash_scores": { "default": -10000 }, "trash_description": "Size: Block sizes over 40GB", "name": "Size: Block More 40GB", "includeCustomFormatWhenRenaming": false, "specifications": [ { "name": "Size", "implementation": "SizeSpecification", "negate": true, "required": true, "fields": { "min": 0, "max": 40 } } ] } ================================================ FILE: custom/cfs/de-tier-01.json ================================================ { "trash_id": "de-tier-01-version1", "trash_scores": {}, "name": "GER HD Rel. Group Tier 01", "includeCustomFormatWhenRenaming": false, "specifications": [ { "name": "ZeroTwo", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "ZeroTwo" } }, { "name": "WAYNE", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "WAYNE" } }, { "name": "TSCC", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "TSCC" } }, { "name": "DETAiLS", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "DETAiLS" } }, { "name": "FoST", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "FoST" } }, { "name": "SAUERKRAUT", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "SAUERKRAUT" } }, { "name": "Baka (Anime)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "Baka" } }, { "name": "D02KU", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "D02KU" } }, { "name": "WvF", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "WvF" } } ] } ================================================ FILE: custom/cfs/de-tier-02.json ================================================ { "trash_id": "de-tier-02-version1", "trash_scores": {}, "name": "GER HD Rel. Group Tier 02", "includeCustomFormatWhenRenaming": false, "specifications": [ { "name": "iNTENTiON", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "iNTENTiON" } }, { "name": "TVS (keine ENG subs?)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "TVS" } }, { "name": "TV4A (check ob Tier 01)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "TV4A" } }, { "name": "TvR", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "TvR" } }, { "name": "TVARCHiV", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "TVARCHiV" } }, { "name": "RUBBiSH", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "RUBBiSH" } }, { "name": "MGE", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "MGE" } }, { "name": "HAXE", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "HAXE" } }, { "name": "RSG", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "RSG" } }, { "name": "AWARDS (Inactive)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "AWARDS" } }, { "name": "TMSF", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "TMSF" } }, { "name": "HQC (Inactive)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "HQC" } }, { "name": "DMPD", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "DMPD" } }, { "name": "MiSFiTS (Inactive)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "MiSFiTS" } }, { "name": "4SJ (Inactive)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "4SJ" } }, { "name": "euHD (Inactive)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "euHD" } }, { "name": "FuN (Low Size 265)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "FuN" } }, { "name": "OCA (Inactive)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "OCA" } }, { "name": "JaJunge", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "JaJunge" } }, { "name": "RWP", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "RWP" } }, { "name": "WOTT", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "WOTT" } } ] } ================================================ FILE: custom/cfs/de-tier-03.json ================================================ { "trash_id": "de-tier-03-version1", "trash_scores": {}, "name": "GER HD Rel. Group Tier 03", "includeCustomFormatWhenRenaming": false, "specifications": [ { "name": "AIDA", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "AIDA" } }, { "name": "SunDry", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "SunDry" } }, { "name": "TVP (Inactive)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "TVP" } }, { "name": "UTOPiA", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "UTOPiA" } }, { "name": "VECTOR (Evaluate 07.2024)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "VECTOR" } }, { "name": "EXCiTED (Inactive)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "EXCiTED" } }, { "name": "FRAGGERS (Inactive)", "implementation": "ReleaseGroupSpecification", "negate": false, "required": false, "fields": { "value": "FRAGGERS" } } ] } ================================================ FILE: custom/cfs/lang-de-dl-2.json ================================================ { "trash_id": "lang-de-dl-2-version1", "trash_scores": {}, "name": "German DL 2", "includeCustomFormatWhenRenaming": false, "specifications": [ { "name": "NOT German DL", "implementation": "ReleaseTitleSpecification", "negate": true, "required": true, "fields": { "value": "(?i)german\\s*\\.?dl|(?<=\\bGerman\\b.*)(? pnpm deploy ``` If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. ================================================ FILE: docs/docs/changelog.mdx ================================================ --- sidebar_position: 8 description: "Changelog / Version changes" keywords: [changelog, version] title: Changelog --- import CodeBlock from "@theme/CodeBlock"; import { default as CHANGELOG } from "../../CHANGELOG.md"; # ================================================ FILE: docs/docs/comparison.mdx ================================================ --- sidebar_position: 7 description: "Comparison of Configarr to other tools" keywords: [comparison, recyclarr, notifiarr] --- # Comparison As Configarr is not the only tool around we will compare different tools based on feature sets in this sections. The main focus of Configarr is the full support of TRaSH-Guide and combine it with maximum customizability by the user. That's also the most mentionable contrast to all other tools which do not provide this flexibility as shown in the matrix. Focused together for seamless experience in containerized environments with docker and kubernetes. Notes: - TRaSH-Guide prefix means that we support the TRaSH-Guide provided JSON files in the repository [Repo](https://github.com/TRaSH-Guides/Guides/tree/master/docs/json) - Custom prefix means that you can create own e.q. custom formats in the tools which are not defined in TRaSH or somewhere. The user can do it directly with the tool in the config. - CustomFormatGroups are support like it makes sense. They are mostly create for interactive purpose which does not makes much sense with Configarr. Default will be loading all required one's and user can enable to load all with a flag. Recommendation is to load optional ones with `custom_formats` ## Radarr | Features |
Configarr
| Notifiarr | Recyclarr | | -------------------------------- | :------------------------------------------: | :----------------: | :----------------: | | GUI (graphical user interface) | | :white_check_mark: | | | TRaSH-Guide Custom Formats | :white_check_mark: | :white_check_mark: | :white_check_mark: | | TRaSH-Guide Custom Format Groups | :white_check_mark: | :white_check_mark: | | | TRaSH-Guide Quality Profiles | :white_check_mark: | :white_check_mark: | | | TRaSH-Guide Quality Sizes | :white_check_mark: | :white_check_mark: | :white_check_mark: | | TRaSH-Guide Naming | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Custom Custom Formats | :white_check_mark: | | | | Custom Quality Profiles | :white_check_mark: | :memo: \*1 | :white_check_mark: | | Custom Quality Sizes | :white_check_mark: | | | | Custom Naming | :white_check_mark: | | | | Clear all Custom Formats | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Modify Scores | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Profile renaming | :white_check_mark: | :white_check_mark: | | | Profile cloning | :white_check_mark: | | |
\*1: You start with one of the provided templates and can adjust things. But not just start with a clean QualityProfile.
## Sonarr | Features |
Configarr
| Notifiarr | Recyclarr | | -------------------------------- | :------------------------------------------: | :----------------: | :----------------: | | GUI (graphical user interface) | | :white_check_mark: | | | TRaSH-Guide Custom Formats | :white_check_mark: | :white_check_mark: | :white_check_mark: | | TRaSH-Guide Custom Format Groups | :white_check_mark: | :white_check_mark: | | | TRaSH-Guide Quality Profiles | :white_check_mark: | :white_check_mark: | | | TRaSH-Guide Quality Sizes | :white_check_mark: | :white_check_mark: | :white_check_mark: | | TRaSH-Guide Naming | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Custom Custom Formats | :white_check_mark: | | | | Custom Quality Profiles | :white_check_mark: | :memo: \*1 | :white_check_mark: | | Custom Quality Sizes | :white_check_mark: | | | | Custom Naming | :white_check_mark: | | | | Clear all Custom Formats | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Modify Scores | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Profile renaming | :white_check_mark: | :white_check_mark: | | | Profile cloning | :white_check_mark: | | |
\*1: You start with one of the provided templates and can adjust things. But not just start with a clean QualityProfile.
## Whisparr | Features |
Configarr
| Notifiarr (unsupported) | Recyclarr (unsupported) | | ------------------------------ | :------------------------------------------: | :---------------------: | :---------------------: | | GUI (graphical user interface) | | | | | Custom Custom Formats | :white_check_mark: | | | | Custom Quality Profiles | :white_check_mark: | | | | Custom Quality Sizes | :white_check_mark: | | | | Custom Naming | :white_check_mark: | | | | Clear all Custom Formats | :white_check_mark: | | | | Modify Scores | :white_check_mark: | | | | Profile renaming | :white_check_mark: | | | | Profile cloning | :white_check_mark: | | | ## Readarr | Features |
Configarr
| Notifiarr (unsupported) | Recyclarr (unsupported) | | ------------------------------ | :------------------------------------------: | :---------------------: | :---------------------: | | GUI (graphical user interface) | | | | | Custom Custom Formats | :white_check_mark: | | | | Custom Quality Profiles | :white_check_mark: | | | | Custom Quality Sizes | :white_check_mark: | | | | Custom Naming | :white_check_mark: | | | | Clear all Custom Formats | :white_check_mark: | | | | Modify Scores | :white_check_mark: | | | | Profile renaming | :white_check_mark: | | | | Profile cloning | :white_check_mark: | | | ## Lidarr | Features |
Configarr
| Notifiarr (unsupported) | Recyclarr (unsupported) | | ------------------------------ | :------------------------------------------: | :---------------------: | :---------------------: | | GUI (graphical user interface) | | | | | Custom Custom Formats | :white_check_mark: | | | | Custom Quality Profiles | :white_check_mark: | | | | Custom Quality Sizes | :white_check_mark: | | | | Custom Naming | :white_check_mark: | | | | Clear all Custom Formats | :white_check_mark: | | | | Modify Scores | :white_check_mark: | | | | Profile renaming | :white_check_mark: | | | | Profile cloning | :white_check_mark: | | | ================================================ FILE: docs/docs/concepts.md ================================================ --- sidebar_position: 2 description: "Basic concepts and terminology for understanding Sonarr, Radarr, and custom formats" keywords: [sonarr, radarr, custom formats, quality profiles, media management, automation] --- # What are Arr Applications? This page explains the fundamental concepts and components that Configarr works with. Understanding these will help you make the most of the tool. ## Media Managers ### Sonarr [Sonarr](https://sonarr.tv/) is a TV series management tool that automates the downloading and organizing of TV shows. It can monitor multiple RSS feeds for new episodes and will grab, sort, and rename them. ### Radarr [Radarr](https://radarr.video/) is a movie collection manager that works similarly to Sonarr but focuses on movies instead of TV series. It's designed to automatically download and organize movie files. ## Key Terminology ### Custom Formats Custom formats are rules that help Sonarr and Radarr identify and prioritize specific characteristics of media files. These can include: - Video quality (HDR, DV, etc.) - Audio formats (DTS, TrueHD, etc.) - Release groups - Language specifications - Encoding settings ### Quality Profiles Quality profiles define what types of releases you want for your media. They combine: - Allowed quality types (1080p, 2160p, etc.) - Custom format scores - Upgrade rules - Minimum/maximum size requirements ### Release Groups Release groups are teams or individuals who release media content. Different groups often have different standards and specialties for their releases. ### TRaSH-Guides [TRaSH-Guides](https://trash-guides.info/) is a comprehensive collection of guides and configurations for various media management tools. It provides recommended settings, custom formats, and quality profiles that represent community best practices. ## How They Work Together - **Quality Profiles** use **Custom Formats** to score and select releases - **Sonarr/Radarr** use these profiles to make download decisions - **TRaSH-Guides** provides optimized configurations for both - **Configarr** helps manage and synchronize all these components :::tip For detailed setup instructions and tutorials, visit the official documentation for [Sonarr](https://wiki.servarr.com/sonarr) and [Radarr](https://wiki.servarr.com/radarr). ::: ================================================ FILE: docs/docs/configuration/_category_.json ================================================ { "label": "Configuration", "position": 4, "link": { "type": "generated-index" } } ================================================ FILE: docs/docs/configuration/_include/config-file-sample.yml ================================================ # Optional: Override default repositories #trashGuideUrl: https://github.com/BlackDark/fork-TRASH-Guides #recyclarrConfigUrl: https://github.com/BlackDark/fork-recyclarr-configs # Optional: Specify a custom branch/revision (defaults to 'master') #trashRevision: master #recyclarrRevision: master # since v1.12.0. Optional. Enable for legacy configuration to clone full repos (trash, recyclarr) instead of sparse. # Default is false. Setting to true increases storage usage up to 10x. #enableFullGitClone: true # since v1.22.0. Optional. Enable compatibility mode for TRaSH-Guides changes from Feb 2026. # When true: uses old behavior (exclude semantics for CF groups, reversed quality ordering) # When false (default): uses new behavior (include semantics, display order for qualities) # See: https://github.com/TRaSH-Guides/Guides/commit/2994a7979d8036a7908a92e2cd286054fd4fcc1b #compatibilityTrashGuide20260219Enabled: false # Optional. Silence warnings when a Quality Profile contains CustomFormats marked mutually # exclusive in TRaSH-Guides conflicts.json. Sync behavior is unchanged; only logs are suppressed. # Default is false. #silenceTrashConflictWarnings: true # Optional: Enable anonymous telemetry tracking of feature usage # Default is false. Set to true to help improve Configarr by sharing anonymous usage statistics. telemetry: true # Optional: Paths for custom formats and templates localCustomFormatsPath: /app/cfs localConfigTemplatesPath: /app/templates # Optional. Custom Format Definitions customFormatDefinitions: - trash_id: example-in-config-cf trash_scores: default: -10000 trash_description: "Language: German Only" name: "Language: Not German" includeCustomFormatWhenRenaming: false specifications: - name: Not German Language implementation: LanguageSpecification negate: true required: false fields: value: 4 # With this options you can disable or enable processing for *arrs. Default is enabled #sonarrEnabled: false #radarrEnabled: false #whisparrEnabled: false #readarrEnabled: false #lidarrEnabled: false # Sonarr Configuration sonarr: instance1: # Instance name (can be any unique identifier) base_url: http://sonarr:8989 # Sonarr instance URL api_key: !secret SONARR_API_KEY # Reference to API key in secrets.yml # api_key: !env SONARR_API_KEY # load from environment variable # api_key: !file /run/secrets/sonarr_api_key # Load from a file # since v1.11.0. You can disable instances. Optional # enabled: false # since v1.12.0. Optional # delete_unmanaged_custom_formats: # enabled: true # ignore: # optional # - some-cf # since v1.18.0. Optional # delete_unmanaged_quality_profiles: # enabled: true # ignore: # optional # - some-qp # experimental since v1.14.0. Optional # root_folders: # - /mnt/media/series # experimental since v1.14.0. Optional # delay_profiles: # default: # enableUsenet: true # enableTorrent: false # preferredProtocol: usenet # usenetDelay: 10 # torrentDelay: 0 # bypassIfHighestQuality: false # bypassIfAboveCustomFormatScore: false # minimumCustomFormatScore: 0 # additional: # - enableUsenet: true # enableTorrent: false # preferredProtocol: usenet # usenetDelay: 10 # torrentDelay: 0 # bypassIfHighestQuality: false # bypassIfAboveCustomFormatScore: false # minimumCustomFormatScore: 0 # order: 1 # tags: # - delayprofiletest quality_definition: type: series # Quality definition type for Sonarr include: # Template includes - template: sonarr-cf - template: sonarr-quality - template: d1498e7d189fbe6c7110ceaabb7473e6 source: TRASH # RECYCLARR (default) or TRASH # WEB-1080p (recyclarr template) - template: sonarr-quality-definition-series - template: sonarr-v4-quality-profile-web-1080p - template: sonarr-v4-custom-formats-web-1080p # (experimental) since v1.18.0. Load template from URL # - template: https://gist.githubusercontent.com/user/abc123/raw/template.yml # experimental available in all *arr #media_management: {} # experimental available in all *arr #media_naming_api: {} # experimental available in all *arr #ui_config: {} # naming from recyclarr: https://recyclarr.dev/wiki/yaml/config-reference/media-naming/ #media_naming: {} # (experimental) Manage download clients #download_clients: # - name: "Primary qBittorrent" # type: qbittorrent # enable: true # priority: 1 # remove_completed_downloads: true # remove_failed_downloads: true # tags: # - "4K" # - "High Quality" # fields: # host: qbittorrent # port: 8080 # use_ssl: false # url_base: / # username: sonarr # password: changeme # tv_category: series-4k # # # Always update password fields even when they match the server # update_password: false # # Delete unmanaged download clients # delete_unmanaged: # enabled: true # ignore: # - "Manual Test Client" # # Global download client configuration # config: # download_client_working_folders: "/downloads,/tmp" # enable_completed_download_handling: true # auto_redownload_failed: false # auto_redownload_failed_from_interactive_search: false # # Radarr only: Check interval for finished downloads (in minutes) # check_for_finished_download_interval: 5 # # Note: auto_redownload_failed_from_interactive_search is not available in Whisparr # (experimental) since v1.12.0 # allows using the cf-groups from TRaSH-Guide. custom_format_groups: - trash_guide: - id: c4735e1d02e8738044ad4ad1bf58670c # Multiple CFs, default only required=true are loaded #include_unrequired: true # if you want to load all set this to true assign_scores_to: - name: WEB-1080p custom_formats: # Custom format assignments - trash_ids: - 47435ece6b99a0b477caf360e79ba0bb # x265 (HD) assign_scores_to: - name: WEB-1080p score: 0 - trash_ids: - a3d82cbef5039f8d295478d28a887159 # block HDR10+ - 2b239ed870daba8126a53bd5dc8dc1c8 # block DV HDR10+ assign_scores_to: - name: WEB-1080p score: -10000 - trash_ids: - example-in-config-cf # custom format defined in config.yml assign_scores_to: - name: WEB-1080p score: -5000 quality_profiles: - name: WEB-1080p upgrade: min_format_score: 10000 # Ability to rename quality profiles # renameQualityProfiles: # - from: WEB-1080p # to: RenamedProfile # Ability to clone profiles # cloneQualityProfiles: # - from: RenamedExampleProfile # to: ClonedProfile # Radarr Configuration radarr: instance1: # Instance name (can be any unique identifier) base_url: http://radarr:7878 # Radarr instance URL api_key: !secret RADARR_API_KEY # Reference to API key in secrets.yml quality_definition: type: movie # Quality definition type for Radarr include: # Comment out any of the following includes to disable them - template: radarr-quality-definition-movie - template: radarr-quality-profile-hd-bluray-web - template: radarr-custom-formats-hd-bluray-web custom_formats: # Custom format assignments - trash_ids: - 9f6cbff8cfe4ebbc1bde14c7b7bec0de # IMAX Enhanced assign_scores_to: - name: HD Bluray + WEB score: 0 quality_profiles: - name: HD Bluray + WEB # Support added with 1.7.0. Not support in all *arr applications. Check the application if it is supported. language: Any # The name must match available names in *arr # Reset existing CustomFormats scores on profile reset_unmatched_scores: enabled: true upgrade: allowed: true until_quality: Remux-1080p until_score: 10000 # Upgrade until score min_format_score: 100 # The minimum increment to trigger an upgrade min_format_score: 100 # The most important custom format needed to download # Score set from TRaSH-Guide to use #score_set: anime-radarr # Sorting order of qualities in profile. Either top or bottom #quality_sort: top # How to group and sort profiles qualities: - name: Remux-1080p qualities: - Bluray-1080p - Remux-1080p - name: WEB 1080p qualities: - WEBDL-1080p - WEBRip-1080p - HDTV-1080p - name: Bluray-720p - name: WEB 720p qualities: - WEBDL-720p - WEBRip-720p - HDTV-720p - name: Bluray-576p - name: Bluray-480p - name: WEB 480p qualities: - WEBDL-480p - WEBRip-480p - name: DVD - name: SDTV # experimental support: check https://configarr.rayak.de/docs/configuration/experimental-support whisparr: {} # experimental support: check https://configarr.rayak.de/docs/configuration/experimental-support readarr: {} # experimental support: check https://configarr.rayak.de/docs/configuration/experimental-support lidarr: {} ================================================ FILE: docs/docs/configuration/_include/unmanaged-customformats.yml ================================================ sonarr: instance1: base_url: http://sonarr:8989 api_key: !secret SONARR_API_KEY # since v1.13.0. You can assign custom formats to quality profiles which are only managed on the server custom_formats: - trash_ids: - 47435ece6b99a0b477caf360e79ba0bb # x265 (HD) assign_scores_to: - name: Any # 'Any' already exists on server # quality_profiles: # - name: Any # # ... ================================================ FILE: docs/docs/configuration/config-file.md ================================================ --- sidebar_position: 2 title: Configuration File description: "Learn how to configure Configarr using config.yml, environment variables, and optional secrets.yml" keywords: [configarr configuration, yaml config, secrets management, custom formats] --- import CodeBlock from "@theme/CodeBlock"; import ConfigFileSample from "!!raw-loader!./\_include/config-file-sample.yml"; import ExampleUnamanagedCustomFormats from "!!raw-loader!./\_include/unmanaged-customformats.yml"; # Configuration Files Configarr uses one required configuration file and one optional file for secrets: - `config.yml` - Required. Contains your main configuration. - `secrets.yml` - Optional. Stores sensitive information when you use `!secret`. ## Usage 1. Create `config.yml` 2. Decide how you want to provide sensitive values: - Use `!env` and inject environment variables (recommended for containers/Kubernetes) - Or use `!secret` and provide a `secrets.yml` file 3. Place your configuration files in the Configarr configuration directory 4. For Docker/Kubernetes, pass secrets using environment variables or mounted secret files Configarr will automatically load these configurations on startup and apply them to your Sonarr/Radarr instances. ## Configuration Structure We try to be mostly compatible with Recyclarr, but with some small differences. We started this fork since Recyclarr V7 and will not always support newer features. Additionally we implement new features which recyclarr does not support at all like custom formats definitions directly in config or support local folders. ### Templates Configarr supports multiple types of templates: 1. **Recyclarr Templates**: Used to define reusable configuration blocks - In Recyclarr also named: `Pre-Built Configuration Files` - Documentation: [Recyclarr Templates Wiki](https://recyclarr.dev/wiki/guide-configs/) - Location: Place template files in the directory specified by `localConfigTemplatesPath` 2. **TRaSH-Guides Templates**: Standard templates from TRaSH-Guides - These are automatically pulled from the TRaSH-Guides repository - `language` field support added with `1.7.0` - Can be overridden using `trashGuideUrl` in config.yml - See [TRaSH-Guides Radarr](https://github.com/TRaSH-Guides/Guides/tree/master/docs/json/radarr/quality-profiles) and [TRaSH-Guides Sonarr](https://github.com/TRaSH-Guides/Guides/tree/master/docs/json/sonarr/quality-profiles) for more information - You must also check all CF-Groups because they will be also included automatically (this is desired by the TRaSH-Guide) - [TRaSH-Guides Radarr CF Groups](https://github.com/TRaSH-Guides/Guides/tree/master/docs/json/radarr/cf-groups) - [TRaSH-Guides Sonarr CF Groups](https://github.com/TRaSH-Guides/Guides/tree/master/docs/json/sonarr/cf-groups) - [Github PR/Explanation](https://github.com/TRaSH-Guides/Guides/pull/2455#discussion_r2297832409) - [Discord Discussion/Explanation](https://discord.com/channels/492590071455940612/1409911784386596894) 3. **URL Templates** 1.18.0 Experimental: Load templates directly from HTTP/HTTPS URLs - Allows sharing configurations without copying files or forking repositories - Supports both Recyclarr format (YAML) and TRaSH-Guides format (JSON) templates - Simply provide a URL to a template file in the `include` section - The URL must be accessible via HTTP GET request **Recyclarr Format (YAML):** ```yaml title="config.yml" sonarr: instance1: # ... include: - template: https://gist.githubusercontent.com/user/abc123/raw/template.yml - template: https://example.com/path/to/template.yml - template: local-template-name # Still works with local/recyclarr templates ``` **TRaSH-Guides Format (JSON):** ```yaml title="config.yml" sonarr: instance1: # ... include: - template: https://gist.githubusercontent.com/user/abc123/raw/trash-template.json source: TRASH - template: https://example.com/path/to/trash-profile.json source: TRASH ``` **Notes:** - **Experimental**, available since `v1.18.0` - URL templates are processed first, before local and Recyclarr templates - Failed URL fetches are logged as warnings and skipped gracefully - Recyclarr format templates must be valid YAML files following the Recyclarr template format - TRaSH-Guides format templates must be valid JSON files following the TRaSH-Guides quality profile format (must include `trash_id` field) - When loading TRaSH-Guides templates from URLs, specify `source: TRASH` in the include entry - Network requests have a 30-second timeout ### Repository URL Configuration You can override the default repository URLs for TRaSH-Guides and Recyclarr templates: ```yaml title="config.yml" # Use a custom TRaSH-Guides fork trashGuideUrl: https://github.com/your-org/fork-TRASH-Guides # Use a custom Recyclarr templates fork recyclarrConfigUrl: https://github.com/your-org/fork-recyclarr-configs # Optional: Specify a custom branch/revision (defaults to 'master') trashRevision: main recyclarrRevision: develop ``` **Repository URL Changes:** When you change `trashGuideUrl` or `recyclarrConfigUrl` in your config: - Configarr automatically detects existing cached repositories - If the remote URL has changed, it deletes the old repository and re-clones from the new URL - The new repository is cloned fresh, avoiding any divergent branch issues - If the revision doesn't exist in the new repository, a clear error message is provided - **No manual cache deletion is required** - changes take effect on the next run **Example Scenario:** 1. Start with default TRaSH-Guides repository 2. Change `trashGuideUrl` to a custom fork in your config 3. Run Configarr - it automatically detects the URL change, deletes the old cache, and clones from the new repository 4. Done! No manual intervention needed. **Error Handling:** If something goes wrong during repository updates: - Clear error messages are logged explaining what failed - The revision may not exist in the new repository - The new URL may not be accessible - Check the logs for guidance on how to resolve the issue ## Configuration Files Reference If you want to deep dive into available values and parameters you can always check the direct source code reference for available configurations: [Source Code](https://github.com/raydak-labs/configarr/blob/main/src/types/config.types.ts) ### config.yml The main configuration file that defines your Sonarr and Radarr instances, custom formats, and template includes.
Config.yml {ConfigFileSample}
### secrets.yml Store sensitive information like API keys in this file when using `!secret`. Never commit this file to version control. ```yaml title="secrets.yml" SONARR_API_KEY: your_sonarr_api_key_here RADARR_API_KEY: your_radarr_api_key_here ``` **Multiple secrets and globs** 1.21.0 `SECRETS_LOCATION` can be a comma-separated list of files and/or glob patterns. All matched files are loaded and merged; later files override earlier ones. ```bash SECRETS_LOCATION=./config/secrets.yml,./config/overrides.yml SECRETS_LOCATION=./config/secrets/*.yml ``` If a single non-glob path is provided and the file doesn't exist, Configarr fails on startup. If a glob has no matches, it continues with empty secrets and logs a warning. ### Value sources (`!secret`, `!env`, `!file`) Configarr supports custom YAML tags to load values from different sources: - `!secret`: Loads a key from `secrets.yml` - `!env`: Loads an environment variable - `!file`: Loads the contents of a file ```yaml title="config.yml" sonarr: series: base_url: !env SONARR_URL api_key: !env SONARR_API_KEY radarr: default: base_url: !secret RADARR_URL api_key: !secret RADARR_API_KEY ``` For Kubernetes, using `!env` is usually the easiest approach because values can come directly from Kubernetes Secrets via container environment variables. ### Enable/Disable You can configure enabled `*Arr` instance with options in the `config.yml` file. Default everything is `true`. ```yml # true or false sonarrEnabled: false radarrEnabled: false whisparrEnabled: false readarrEnabled: false lidarrEnabled: false # You can also disable on per instance basis sonarr: instance1: # ... enabled: false ``` ### Telemetry 1.16.0 {#telemetry} Configarr can optionally collect anonymous telemetry data to help improve the application. This includes information about which features are being used, but no personal data, API keys, or configuration details are collected. To enable telemetry, add the following to your `config.yml`: ```yaml telemetry: true ``` **Note:** Telemetry is disabled by default and is completely opt-in. See [Telemetry](./telemetry.md) ### TRaSH CustomFormat conflicts 1.26.0 {#trash-cf-conflicts} Configarr parses `conflicts.json` from TRaSH-Guides and logs a warning when a Quality Profile is configured with two or more CustomFormats that TRaSH marks as mutually exclusive. Sync behavior is **not** changed — the warning is informational only, so you can review whether the combination is intentional. The check runs automatically for Radarr and Sonarr instances whenever `conflicts.json` is available in the TRaSH-Guides repository. #### Silence conflict warnings 1.27.0 {#silence-trash-conflict-warnings} If you intentionally configure conflicting CustomFormats (or simply want quieter logs), set the top-level flag to skip the check: ```yaml silenceTrashConflictWarnings: true ``` Default is `false`. Sync behavior is identical either way — only the warning log is suppressed. ### Sharing download client config with YAML anchors 1.23.0 {#yaml-anchors} You can avoid repeating the same download client settings by using **YAML anchors** and **merge keys**: - **Anchors** (`&name`): Define a block once and give it a name. - **Aliases** (`*name`): Reuse that block by reference. - **Merge key** (`<<: *name`): Merge the anchored block into the current mapping; any keys you add after it override the anchored values. This works only when **merge keys are enabled**. Set the environment variable **`CONFIGARR_ENABLE_MERGE=true`** (see [Environment Variables](environment-variables.md)); otherwise `<<` is not interpreted as a merge key and your config may fail to parse or behave unexpectedly. **Example: shared base with anchors and merge** ```yaml title="config.yml (requires CONFIGARR_ENABLE_MERGE=true)" x-download-clients: # Define an anchor for shared instance qb_base: &qb_base name: "qBit" type: qbittorrent enable: true priority: 1 remove_completed_downloads: true remove_failed_downloads: true # YAML does a shallow merge, thus we must declare another anchor for the nested dictionary if we plan to override values in it fields: &qb_fields host: qbittorrent port: 8080 use_ssl: false username: admin password: changeme sonarr: instance1: base_url: http://sonarr:8989 api_key: !secret SONARR_API_KEY download_clients: data: - <<: *qb_base fields: <<: *qb_fields tv_category: series tags: ["sonarr"] # Reuse same base, override name and fields - <<: *qb_base name: "qBit 4K" fields: <<: *qb_fields tv_category: series-4k tags: ["4K"] update_password: false delete_unmanaged: enabled: true ignore: ["Manual Test Client"] config: enable_completed_download_handling: true auto_redownload_failed: false ``` The anchor (`qb_base: &qb_base`) can live at any level, inside a different key (as above), or at the top level. Each list item merges `*qb_base` with `<<:` and then overrides properties as needed. Without `CONFIGARR_ENABLE_MERGE=true`, use fully inline entries (no `<<`) as in the example at the start of this section. ## Quality Definition / Size Quality definitions control the min/max/preferred file sizes for each quality level. There are three ways to configure them: ### Method 1: Reference a TRaSH-Guides definition by type (classic) The `type` value must match the filename (without `.json`) in the TRaSH-Guides [`quality-size`](https://github.com/TRaSH-Guides/Guides/tree/master/docs/json) directory. **Radarr** — available `type` values: | `type` | Description | | --------------- | ----------------------------------------- | | `movie` | Standard movie sizes | | `anime` | Anime movie sizes | | `sqp-streaming` | Streaming Preferred quality profile sizes | | `sqp-uhd` | UHD Streaming quality profile sizes | **Sonarr** — available `type` values: | `type` | Description | | -------- | ------------------------ | | `series` | Standard TV series sizes | | `anime` | Anime series sizes | ```yml radarr: instance1: quality_definition: type: movie # matches radarr/quality-size/movie.json preferred_ratio: 0.5 # optional: 0.0 (min) to 1.0 (max), default uses TRaSH preferred sonarr: instance1: quality_definition: type: series # matches sonarr/quality-size/series.json ``` > **Hint:** `type` (filename-based) may be deprecated in favor of `trash_id` in a future version. > See [GitHub Issue #155](https://github.com/raydak-labs/configarr/issues/155). ### Method 2: Include a quality definition via `include` (auto-detected) When you include a TRaSH JSON file with `source: TRASH`, Configarr automatically detects whether it is a quality profile or a quality definition and routes it accordingly. This works for both named trash_id references and URL templates. **By trash_id:** ```yml radarr: instance1: include: - template: aed34b9f60ee115dfa7918b742336277 # movie quality definition source: TRASH preferred_ratio: 0.5 # optional: only applies when include resolves to a QD sonarr: instance1: include: - template: bef99584217af744e404ed44a33af589 # series quality definition source: TRASH ``` **By URL:** ```yml radarr: instance1: include: - template: https://raw.githubusercontent.com/TRaSH-Guides/Guides/master/docs/json/radarr/quality-size/movie.json source: TRASH preferred_ratio: 0.5 ``` **trash_id reference table:** | Arr | `type` | `trash_id` | | ------ | --------------- | ---------------------------------- | | Radarr | `movie` | `aed34b9f60ee115dfa7918b742336277` | | Radarr | `anime` | `c2aa9540a57d273a9e03a538efe0ca1b` | | Radarr | `sqp-streaming` | `8f1391784833965c476bb6aee95fe328` | | Radarr | `sqp-uhd` | `da8c8c0268b2f304be588132831543d2` | | Sonarr | `series` | `bef99584217af744e404ed44a33af589` | | Sonarr | `anime` | `387e6278d8e06083d813358762e0ac63` | ### Method 3: Manual quality sizes Override individual quality sizes directly — useful for fine-tuning without loading a full TRaSH definition. Can be combined with either method above (manual entries are applied last and take precedence for matching quality names). ```yml sonarr: instance1: quality_definition: qualities: - quality: "HDTV-720p" # must match the name shown in the *arr UI title: AdjustedName # optional: rename in UI min: 17.1 preferred: 500 max: 1000 # Or in a template file: quality_definition: qualities: - quality: "HDTV-1080p" min: 20 preferred: 500 max: 1000 ``` **Notes:** - `preferred_ratio` (0.0 – 1.0) interpolates between `min` and `max` to compute `preferred`. It applies to `type`-based and `include`-based loading; it has no effect on manual `qualities`. - `preferred_ratio` on `include` items applies only to that specific include. - Merge order: TRaSH/Recyclarr templates → local templates → config file (`quality_definition.qualities` last). - Only supported for Radarr and Sonarr. Not available for Lidarr, Readarr, Whisparr. - Available since `v1.9.0`. Include-based QD detection available since `v1.x.0` (TBD). ## Media Naming You can use the predefined naming configurations from TRaSH-Guide like in recyclarr with the `media_naming` key. - [TRaSH-Guide Sonarr Naming](https://github.com/TRaSH-Guides/Guides/blob/master/docs/json/sonarr/naming/sonarr-naming.json) - [TRaSH-Guide Radarr Naming](https://github.com/TRaSH-Guides/Guides/blob/master/docs/json/radarr/naming/radarr-naming.json) - [Recyclarr Wiki](https://recyclarr.dev/wiki/yaml/config-reference/media-naming/) The configuration values differs between Radarr and Sonarr. **Radarr** ```yml radarr: instance1: # Media Naming Configuration media_naming: folder: default movie: rename: true standard: standard ``` | **Property** | **Description** | **Default** | | ---------------- | ----------------------------------------------------------------------------- | ----------- | | `folder` | Key for "Movie Folder Format". Check debug logs or TRaSH-Guide for values. | Not synced | | `movie.rename` | If set to `true`, this enables the "Rename Movies" checkbox in the Radarr UI. | Not synced | | `movie.standard` | Key for "Standard Movie Format". Check debug logs or TRaSH-Guide for values. | Not synced | All configurations above directly affect the "Movie Naming" settings under **Settings > Media Management** in the Radarr UI. If a property is _not specified_, Configarr will not sync that setting, allowing manual configuration. --- **Sonarr** ```yml sonarr: instance1: # Media Naming Configuration media_naming: series: default season: default episodes: rename: true standard: default daily: default anime: default ``` | **Property** | **Description** | **Default** | | ------------------- | ------------------------------------------------------------------------------- | ----------- | | `series` | Key for "Series Folder Format". Check debug logs or TRaSH-Guide for values. | Not synced | | `season` | Key for "Season Folder Format". Check debug logs or TRaSH-Guide for values. | Not synced | | `episodes.rename` | If set to `true`, this enables the "Rename Episodes" checkbox in the Sonarr UI. | Not synced | | `episodes.standard` | Key for "Standard Episode Format". Check debug logs or TRaSH-Guide for values. | Not synced | | `episodes.daily` | Key for "Daily Episode Format". Check debug logs or TRaSH-Guide for values. | Not synced | | `episodes.anime` | Key for "Anime Episode Format". Check debug logs or TRaSH-Guide for values. | Not synced | All configurations above directly affect the "Episode Naming" settings under **Settings > Media Management** in the Sonarr UI. If a property is _not specified_, Configarr will not sync that setting, allowing manual configuration. ## Quality Profile This is general structure of a profile which can be directly in the config or in templates. Some fields could differ between different \*arrs if some features between mismatch. Mostly those should be the same. ```yml # ... sonarr: instance1: # ... quality_profiles: - name: ExampleInConfigProfile reset_unmatched_scores: enabled: true # enable to reset scores upgrade: allowed: true # enable to allow updates until_quality: WEB 2160p # update until quality until_score: 1000 # Upgrade until score min_format_score: 5 # Minimum increment for upgrade min_format_score: 0 # Minimum custom format needed to download quality_sort: top # enable to allow updates qualities: # qualtities enabled in the profile. Can be groups. - name: Remux-2160p - name: WEB 2160p # This a group qualities: - WEBDL-2160p - WEBRip-2160p - name: Remux-1080p - name: WEB 1080p qualities: - WEBDL-1080p - WEBRip-1080p ``` ### Quality Profile Rename {#quality-profile-rename} Support has been added to allow renaming quality profiles. This is useful if you use existing templates for example from TRaSH-Guides but want to adjust the naming to your liking. We achieve the renaming by modifying all names in the quality_profiles fields and custom formats score mappings. ```yml # ... sonarr: instance1: # ... # Ability to rename profiles renameQualityProfiles: - from: ExampleProfile # must be the exact name of the existing profile to: RenamedExampleProfile # will be the new profile ``` Notes: - not supported in templates and will therefore not be merged! - rename order will be displayed in `DEBUG` log like: `DEBUG [16:37:09.377]: Will rename quality profiles in this order: 'ExampleProfile' -> 'RenamedExampleProfile','[German] HD Bluray + WEB' -> 'RenamedProfile'` - **experimental**, available since `v1.10.0` ### Quality Profile Cloning {#quality-profile-clone} Support has been added to allow cloning quality profiles. This is useful if you use existing templates for example from TRaSH-Guides but want to duplicate and slightly adjust some Custom Format scores or mappings. We achieve the clone by duplicating all quality profiles and duplicating all profile references in the custom formats. :::tip The **ordering** of `rename` and `clone` is important. At the moment we `rename` first and then `clone`! ::: ```yml # ... sonarr: instance1: # ... # Ability to clone profiles cloneQualityProfiles: - from: ExampleProfile # must be the exact name of the existing profile to: ClonedProfile1 # will be the new profile ``` Notes: - not supported in templates and will therefore not be merged! - clone order will be displayed in `DEBUG` log - **experimental**, available since `v1.10.0` ## Custom Formats Definitions {#custom-format-definitions} Custom formats can be defined in two ways: 1. **Direct in config.yml**: Define custom formats directly in your configuration file 2. **Separate files**: Store custom formats in separate files in the `localCustomFormatsPath` directory 3. **Local templates**: Store custom formats in local templates folder which can be included per instance (at the moment only for local templates and not recyclarr git templates) Example custom format definition: ```yaml title="config.yml" # Directly in the main config.yml customFormatDefinitions: - trash_id: custom-de-only # Unique identifier trash_scores: default: -10000 # Default score for this format trash_description: "Language: German Only" name: "Language: Not German" includeCustomFormatWhenRenaming: false specifications: - name: Not German Language implementation: LanguageSpecification negate: true required: false fields: value: 4 # ... ``` ```yaml title="local-templates/template1.yml" # or in templates which can be included per instance customFormatDefinitions: - trash_id: custom-de-only2 # Unique identifier trash_scores: default: -10000 # Default score for this format trash_description: "Language: German Only 2" name: "Language: Not German" includeCustomFormatWhenRenaming: false specifications: - name: Not German Language implementation: LanguageSpecification negate: true required: false fields: value: 4 # ... ``` ## Custom Formats - since `v1.13.0` CustomFormats can now also be assigned to Quality Profiles which only exist on the server and are not configured in the config file or included. This means you can only define the custom format mapping and do not have to provide `quality_profiles` if they already exist on the server.
CustomFormats with unmanaged QualityProfiles {ExampleUnamanagedCustomFormats}
- 1.16.0 CustomFormats and CustomFormatGroups do not have to be assigned to a quality profile. If not assigned to a profile they will still be created on the \*arr instance. ## Cleanup / Deleting CustomFormats {#cleanup-custom-formats} You can now enable the option to delete all custom formats which are not managed and used in the quality profiles. Additionally you can provide exceptions which should be ignored from deletions. ```yml # ... sonarr: instance1: # ... # (experimental) since v1.12.0. Optional delete_unmanaged_custom_formats: enabled: true ignore: # optional - some-cf ``` Notes: - **experimental**, available since `v1.12.0` ## Cleanup / Deleting QualityProfiles {#cleanup-quality-profiles} You can now enable the option to delete all quality profiles which are not managed by configarr. Additionally you can provide exceptions on which quality profile(s) should be ignored from deletion. ```yml # ... sonarr: instance1: # ... # (experimental) since v1.18.0. Optional delete_unmanaged_quality_profiles: enabled: true ignore: # optional - some-qp ``` Notes: - **experimental**, available since `v1.18.0` ## CustomFormatGroups {#custom-format-groups} Support has been added to allow using the TRaSH-Guide custom format groups: [see here](https://github.com/TRaSH-Guides/Guides/tree/master/docs/json/sonarr/cf-groups). Those are logically bundled together CustomFormats which will be applied together. TRaSH-Guide is using them in an interactive manner with Notifiarr therefore there are also non required CustomFormats. Configarr will only load required ones (`required: true`). If you need some optional ones just add them with the existing `custom_formats` mapping. Also the `quality_profiles` mapping in the JSON file is ignored because it does not make sense in Configarr. ```yml # ... sonarr: instance1: # ... # (experimental) since v1.12.0 # allows using the cf-groups from TRaSH-Guide. custom_format_groups: - trash_guide: - id: c4735e1d02e8738044ad4ad1bf58670c # Multiple CFs, only where required=true are loaded #include_unrequired: true # if you want to load all set this to true assign_scores_to: - name: MyProfile # (experimental) since v1.16.0 #score: 0 # optional score to assign to all custom formats in this group. You can still override custom format scores via custom_formats ``` Notes: - **experimental**, available since `v1.12.0` ### TRaSH-Guides Breaking Changes (Feb 2026) {#trash-guides-breaking-changes-2026-02} :::warning Breaking Change TRaSH-Guides made significant changes to their JSON structure in February 2026, affecting both CF group semantics and quality profile ordering. ::: For detailed information about what changed, backward compatibility options, and version matrix, see the [TRaSH-Guides Breaking Changes FAQ](../faq.md#trash-guides-breaking-changes-2026-02). With version `v1.22.0` the new format will be processed. ## RootFolders With Configarr you can configure the root folders directly. Just specify the list of your folders and Configarr will delete and create them as specified in the list. ```yml # ... sonarr: instance1: # ... # (experimental) since v1.14.0 root_folders: - /mnt/media/series ``` Notes: - **experimental**, available since `v1.14.0` ## Delay Profiles You can configure and sync Delay Profiles directly in your config. This allows you to manage the download delay logic for Usenet and Torrent protocols, including protocol preference, delays, and tag-based rules. A delay profile without any tags is considered the `default` profile. Any other profiles with tags are `additional` profiles. ```yaml yourarr: instance1: # (experimental) since v1.14.0 delay_profiles: default: enableUsenet: true enableTorrent: false preferredProtocol: usenet usenetDelay: 10 torrentDelay: 0 bypassIfHighestQuality: false bypassIfAboveCustomFormatScore: false minimumCustomFormatScore: 0 additional: - enableUsenet: false enableTorrent: true preferredProtocol: torrent usenetDelay: 0 torrentDelay: 20 bypassIfHighestQuality: true bypassIfAboveCustomFormatScore: false minimumCustomFormatScore: 0 order: 2 tags: - mytag ``` Notes: - **experimental**, available since `v1.14.0` - Supported for Sonarr, Radarr, Whisparr, Lidarr, and Readarr (if the API supports it) - If a delay profile exists on the server but not in your config, it will be deleted - If a delay profile is in your config but not on the server, it will be created (if supported) - If a delay profile differs, it will be updated See example [Radarr API DelayProfile](https://radarr.video/docs/api/#/DelayProfile) for more details on available fields. ## Download Clients 1.19.0 Configarr can (experimentally) manage the **Download Clients** configured in your \*Arr applications (for example qBittorrent, Transmission, SABnzbd, etc.). - Create download clients that exist in the config but not in the \*Arr instance - Optionally delete unmanaged download clients - Manage global download client configuration settings since `v1.19.0` ```yaml title="config.yml (inline, no top-level)" sonarr: instance1: base_url: http://sonarr:8989 api_key: !secret SONARR_API_KEY # (experimental) Manage Sonarr download clients download_clients: data: - name: "qBit 4K" type: qbittorrent enable: true priority: 1 remove_completed_downloads: true remove_failed_downloads: true tags: - "4K" # Tag name (auto-resolved to ID) fields: host: qbittorrent port: 8080 use_ssl: false url_base: / username: sonarr password: changeme tv_category: series-4k # Set to true to always update password otherwise existing passwords will not be updated because we can not retrieve existing passwords update_password: false # Delete unmanaged download clients delete_unmanaged: enabled: true ignore: - "Manual Test Client" # (since v1.19.0) Global download client configuration config: enable_completed_download_handling: true auto_redownload_failed: false auto_redownload_failed_from_interactive_search: false # Radarr only: Check interval for finished downloads (in minutes) # check_for_finished_download_interval: 1 ``` ### Download Client Configuration 1.19.0 The `config` section allows you to manage global download client settings. Please check the \*Arr-specific API for supported fields (in the REST APIs under `DownloadClientConfig`). - convert the camelCase typed fields like `enableCompletedDownloadHandling` to snake_case: `enable_completed_download_handling` **Note:** Instance-specific fields (like `check_for_finished_download_interval` for Radarr) are automatically filtered based on the \*Arr type. Unsupported fields are safely ignored. ### Remote Path Mappings 1.20.0 Remote path mappings allow you to remap remote paths from your download clients to local paths that your \*Arr applications can access. This is useful when your download client is running on a different machine or in a container with different mount paths. ```yaml title="config.yml" radarr: instance1: download_clients: remote_paths: - host: "transmission" remote_path: "/downloads/complete" local_path: "/data/media/downloads/complete" - host: "192.168.1.100" remote_path: "/torrents" local_path: "/mnt/torrents" ``` **Key Points:** - `host`: The hostname or IP address of the download client - `remote_path`: The path as seen by the download client (must be unique combined with host) - `local_path`: The path as accessible by the \*Arr application - Mappings are matched by `host + remote_path` combination (must be unique) - Existing mappings with matching host+remote_path will be updated with new local_path - Mappings that exist on the server but not in config will be deleted For more details, check the \*Arr-specific API documentation under the `RemotePathMapping` resource endpoint. ## Experimental supported fields - Experimental support for `media_management` and `media_naming_api` (since v1.5.0) With those you can configure different settings in the different tabs available per *arr. These fields are under experimental support. The supported elements are dependent on the *arr used. Check the following API documentation of available fields: Naming APIs: - https://radarr.video/docs/api/#/NamingConfig/get_api_v3_config_naming - https://sonarr.tv/docs/api/#/NamingConfig/get_api_v3_config_naming - https://whisparr.com/docs/api/#/NamingConfig/get_api_v3_config_naming - https://readarr.com/docs/api/#/NamingConfig/get_api_v1_config_naming - https://lidarr.audio/docs/api/#/NamingConfig/get_api_v1_config_naming MediaManagement APIs: - https://radarr.video/docs/api/#/MediaManagementConfig/get_api_v3_config_mediamanagement - https://sonarr.tv/docs/api/#/MediaManagementConfig/get_api_v3_config_mediamanagement - https://whisparr.com/docs/api/#/MediaManagementConfig/get_api_v3_config_mediamanagement - https://readarr.com/docs/api/#/MediaManagementConfig/get_api_v1_config_mediamanagement - https://lidarr.audio/docs/api/#/MediaManagementConfig/get_api_v1_config_mediamanagement - Experimental support for `ui_config` (since v1.21.0) Allows configuring UI settings like theme, language, calendar preferences, etc. The supported elements are dependent on the \*arr used. Check the following API documentation of available fields: UI Config APIs: - https://radarr.video/docs/api/#/UiConfig/put_api_v3_config_ui__id_ - https://sonarr.tv/docs/api/#v3/tag/uiconfig/PUT/api/v3/config/ui/{id} - https://whisparr.com/docs/api/#/UiConfig/put_api_v3_config_ui__id_ - https://readarr.com/docs/api/#/UiConfig/put_api_v1_config_ui__id_ - https://lidarr.audio/docs/api/#/UiConfig/put_api_v1_config_ui__id_ ================================================ FILE: docs/docs/configuration/environment-variables.md ================================================ --- sidebar_position: 3 title: Environment Variables description: "Learn about the environment variables used in our application configuration." keywords: [environment variables, configuration, setup] --- # Environment Variables This document outlines the available environment variables for configuring Configarr besides the config files. Each variable can be set to customize the behavior of the application. ## Available Environment Variables | Variable Name | Default Value | Required | Description | | ------------------------------------- | ------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `LOG_LEVEL` | `"info"` | No | Sets the logging level. Options are `trace`, `debug`, `info`, `warn`, `error`, and `fatal`. | | `LOG_STACKTRACE` | `"false"` | No | (Experimental, v1.11.0) Outputs additionally stacktraces of underlying errors. | | `CONFIG_LOCATION` | `"./config/config.yml"` | No | Specifies the path to the configuration file. | | `SECRETS_LOCATION` | `"./config/secrets.yml"` | No | Specifies the path to the secrets file. Since `v1.21.0`, can be a comma-separated list and/or glob patterns; later files override earlier ones. | | `CUSTOM_REPO_ROOT` | `"./repos"` | No | Defines the root directory for custom repositories. | | `ROOT_PATH` | Current working directory | No | Sets the root path for the application. Defaults to the current working directory. | | `DRY_RUN` | `"false"` | No | When set to `"true"`, runs the application in dry run mode without making changes. | | `LOAD_LOCAL_SAMPLES` | `"false"` | No | If `"true"`, loads local sample data for testing purposes. | | `DEBUG_CREATE_FILES` | `"false"` | No | Enables debugging for file creation processes when set to `"true"`. | | `TZ` | `"Etc/UTC"` | No | Timezone for the container. | | `STOP_ON_ERROR` | `"false"` | No | (Experimental, v1.11.0) Stop execution on any error on any instance. | | `TELEMETRY_ENABLED` | `undefined` | No | Enables anonymous telemetry tracking of feature usage. Takes precedence over config file setting. | | `CONFIGARR_DISABLE_GIT_CLONE_OPTIONS` | `undefined` | No | Disables custom git clone options (`--filter=blob:none` and `--sparse`). Use this if you encounter errors like "Function not implemented" or "index-pack failed" with legacy kernels. See [troubleshooting](../faq.md#git-clone-errors-with-legacy-kernels) for more details. | | `CONFIGARR_ENABLE_MERGE` | `"false"` | No | When set to `"true"`, enables YAML merge keys (`<<`) when parsing the main config file, so you can use anchors and merge keys to share and override config blocks. See [config file](config-file.md) for details. | ## Usage To use these environment variables, set them in your shell or include them in your deployment configuration via docker or kubernetes. ## Examples - For example you change the default path for all configs, repos with the `ROOT_PATH` variables. As default it would store them inside the application directory (in the container this is `/app`) ## References Check the `.env.template` file in the repository [Github](https://github.com/raydak-labs/configarr/blob/main/.env.template) ================================================ FILE: docs/docs/configuration/experimental-support.md ================================================ --- sidebar_position: 4 title: Experimental Support description: "Experimental and testing support for other *Arr tools" keywords: [configarr configuration, yaml config, custom formats, expermintal, whisparr, readarr, lidarr] --- # Experimental support This section describes experimental support for other \*Arr tools. This means that some features of configarr are working as expected but not every feature must be supported. :::warning This is experimental and testing support. Support could be dropped in the future. ::: ## Whisparr v3 Experimental support for Whisparr was added with [v1.4.0](https://github.com/raydak-labs/configarr/releases/tag/v1.4.0). Configuration is mostly equal to the Sonarr or Radarr. Following things are currently not supported or tested: - quality definition preset is not evaluated ```yaml quality_definition: type: movie # not checked yet ``` - initial language of quality profiles is not correct -> `0` - no available presets because nothings provided in TRaSH-Guides or recyclarr -> needs to be done manually with local templates and custom formats ### Configuration File Check [configuration file reference](/docs/configuration/config-file#custom-format-definitions) for more information. ```yaml title="config.yml" localCustomFormatsPath: /app/cfs localConfigTemplatesPath: /app/templates customFormatDefinitions: - trash_id: example-in-config-cf trash_scores: default: -10000 trash_description: "Language: German Only" name: "Language: Not German" includeCustomFormatWhenRenaming: false specifications: - name: Not German Language implementation: LanguageSpecification negate: true required: false fields: value: 4 # experimental support: check https://configarr.rayak.de/docs/configuration/experimental-support whisparr: instance1: # Instance name (can be any unique identifier) base_url: http://whisparr:6969 # instance URL api_key: !secret WHISPARR_API_KEY # Reference to API key in secrets.yml quality_definition: type: movie # TODO: not checked yet include: # only custom defined templates available - template: whisparr custom_formats: # Custom format assignments - trash_ids: - example-in-config-cf assign_scores_to: - name: ExampleProfile score: 1000 quality_profiles: # TODO: language not correctly mapped - name: ExampleProfile upgrade: until_score: 200 # Not supported in whisparr #min_format_score: 200 ``` ## Readarr v1 Experimental support for Readarr was added with [v1.4.0](https://github.com/raydak-labs/configarr/releases/tag/v1.4.0). Metadata profiles support was added with [v1.19.0](https://github.com/raydak-labs/configarr/releases/tag/v1.19.0). Configuration is mostly equal to the Sonarr or Radarr. Following things are currently not supported or tested: - quality definition preset is not evaluated ```yaml quality_definition: type: movie # not checked yet ``` - no available presets because nothings provided in TRaSH-Guides or recyclarr -> needs to be done manually with local templates and custom formats ### Configuration File Check [configuration file reference](/docs/configuration/config-file#custom-format-definitions) for more information. ```yaml title="config.yml" localCustomFormatsPath: /app/cfs localConfigTemplatesPath: /app/templates customFormatDefinitions: - trash_id: example-release-title-cf trash_scores: default: 0 name: ExampleReleaseTitleCF includeCustomFormatWhenRenaming: false specifications: - name: Preferred Words implementation: ReleaseTitleSpecification negate: false required: false fields: value: "\\b(SPARKS|Framestor)\\b" # experimental support: check https://configarr.rayak.de/docs/configuration/experimental-support readarr: instance1: # Instance name (can be any unique identifier) base_url: http://readarr:8787 # instance URL api_key: !secret READARR_API_KEY # Reference to API key in secrets.yml # not supported # quality_definition: # type: movie # Quality definition type include: # only custom defined templates available - template: readarr custom_formats: # Custom format assignments - trash_ids: - example-release-title-cf assign_scores_to: - name: ExampleProfile score: 1000 quality_profiles: - name: ExampleProfile upgrade: until_score: 200 # Metadata Profiles (since v1.19.0) metadata_profiles: - name: Standard min_popularity: 10 skip_missing_date: true skip_missing_isbn: false skip_parts_and_sets: false skip_secondary_series: false allowed_languages: - eng # ISO 639-3 language codes - deu - null # Allow books with no language min_pages: 50 must_not_contain: - "Abridged" - "Large Print" # Delete unmanaged metadata profiles (since v1.19.0) delete_unmanaged_metadata_profiles: enabled: true ignore: - Default ``` :::tip Language Codes Readarr metadata profiles use **ISO 639-3** language codes (3-letter codes like `eng`, `deu`, `fra`). ::: ## Lidarr v2 Experimental support for Lidarr was added with [v1.8.0](https://github.com/raydak-labs/configarr/releases/tag/v1.8.0). Configuration is mostly equal to the Sonarr or Radarr. Following things are currently not supported or tested: - quality definition preset is not evaluated ```yaml quality_definition: type: movie # not checked yet ``` - no available presets because nothings provided in TRaSH-Guides or recyclarr -> needs to be done manually with local templates and custom formats ### Configuration File Check [configuration file reference](/docs/configuration/config-file#custom-format-definitions) for more information. ```yaml title="config.yml" localCustomFormatsPath: /app/cfs localConfigTemplatesPath: /app/templates customFormatDefinitions: - trash_id: example-release-title-cf trash_scores: default: 0 name: ExampleReleaseTitleCF includeCustomFormatWhenRenaming: false specifications: - name: Preferred Words implementation: ReleaseTitleSpecification negate: false required: false fields: value: "\\b(SPARKS|Framestor)\\b" # experimental support: check https://configarr.rayak.de/docs/configuration/experimental-support lidarr: instance1: # Set the URL/API Key to your actual instance base_url: http://lidarr:8686 api_key: !secret LIDARR_API_KEY # not supported # quality_definition: # type: movie # Quality definition type include: # only custom defined templates available - template: lidarr custom_formats: # Custom format assignments - trash_ids: - example-release-title-cf assign_scores_to: - name: ExampleProfile score: 1000 quality_profiles: # TODO: language not correctly mapped - name: ExampleProfile upgrade: until_score: 200 # Not supported #min_format_score: 200 # Metadata Profiles (since v1.19.0) metadata_profiles: - name: Standard # at least one required primary_types: - Album - EP - Single # at least one required secondary_types: - Studio - Compilation - Soundtrack # at least one required release_statuses: - Official # Delete unmanaged metadata profiles (since v1.19.0) delete_unmanaged_metadata_profiles: enabled: true ignore: - SomeProfile ``` ### Lidarr Metadata Profile Fields | Field | Type | Description | | ------------------ | ------------ | ------------------------------------------------------------------------------------- | | `name` | string | **Required.** Profile name (must be unique) | | `primary_types` | string array | **Required.** List of enabled primary album types (Album, EP, Single, Broadcast) | | `secondary_types` | string array | **Required.** List of enabled secondary album types (Studio, Live, Compilation, etc.) | | `release_statuses` | string array | **Required.** List of enabled release statuses (Official, Promotion, Bootleg, etc.) | **How it works:** - Only types/statuses listed in the arrays will be **enabled** (allowed) - All other types/statuses will be **disabled** **Example:** ```yaml metadata_profiles: - name: Standard primary_types: [Album, EP] # Only Album and EP enabled secondary_types: [Studio, Compilation] # Only Studio and Compilation enabled release_statuses: [Official] # Only Official enabled ``` ## Metadata Profiles - Common Configuration Both Readarr and Lidarr support metadata profiles to control what content is accepted. ### Delete Unmanaged Profiles You can automatically delete metadata profiles that exist on the server but are not defined in your configuration. **Simple form:** ```yaml delete_unmanaged_metadata_profiles: true ``` **Full form with ignore list:** ```yaml delete_unmanaged_metadata_profiles: enabled: true ignore: - LegacyProfile - CustomProfile ``` :::warning Built-in Protection The `None` profile (Lidarr/Readarr) is **always** protected from deletion, even if not in the ignore list. ::: ### Templates and Metadata Profiles Metadata profiles can be defined in templates and merged with instance configurations. **Template:** ```yaml title="templates/readarr.yml" metadata_profiles: - name: Standard min_popularity: 10 delete_unmanaged_metadata_profiles: enabled: true ignore: [] ``` **Instance:** ```yaml title="config.yml" readarr: instance1: include: - template: readarr metadata_profiles: - name: Audiobooks min_popularity: 5 ``` **Result:** Instance has both "Standard" (from template) and "Audiobooks" (from instance). ### Best Practices 1. **Test with dry run first:** ```bash DRY_RUN=true npm start ``` 2. **Use ISO 639-3 language codes** for Readarr (e.g., `eng`, `deu`, not `en`, `de`) 3. **Be explicit about deletion** - always specify ignore list: ```yaml delete_unmanaged_metadata_profiles: enabled: true ignore: - Legacy ``` 4. **Use templates** for shared profiles across instances ================================================ FILE: docs/docs/configuration/general.md ================================================ --- sidebar_position: 1 title: Basics description: "Here we describe how configarr generally works and how things are done." keywords: [general, concept, merge, order, basic] --- # Basics Here we try to explain how things are handled and done in configarr so you understand how and when things happen. ## Merge strategies and orderings Because we are working with multiple files, orders, includes and more merging needs to be handled. What kind of data sets do we have? - TRaSH Repository (CustomFormats, QualityProfiles, QualityDefinition) - Recyclarr Templates (QualityProfiles) - Local Files (CustomFormats, Templates) - Templates (CustomFormats, QualityProfiles) - Config file (CustomFormats, QualityProfiles) The general concept is: more precise or better closer to the main `config` the later it will be merged and takes precendence. At the moment we have the following order: - TRaSH - Recyclarr templates - Local Files - Config file (global level) - Config file (instance level) And this applies for all kind of things: CustomFormats how they are loaded and probably overwritten, QualityProfiles, CustomFormat Mappings to QualityProfiles. If we find some duplicates we will print a log message that something is overwritten or will be ignored. If you find somethting which does not work as expected please create an issue so we can investigate and fix it. ## Folder structure {#folder-structure} Configarr uses following folders for storing configurations, cache or data. Some of those can be configured via configuration others via environment variables. | Folder | Default in container | Required | Description | | ----------- | -------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cfs` | `unset` | No | Optional. Defines location for own custom formats in JSON format (like TRaSH-Guide uses it). Those are directly available your configuration. | | `templates` | `unset` | No | Optional. Location for your own templates to be included. | | `config` | `/app/config` | Yes | Specifies the path to the configuration folder containing the `config.yml` and `secrets.yml` file. | | `repos` | `/app/repos` | Yes | Location for the repos which are cloned and cached (like TRaSH-Guide, Recyclarr configs). Added with `1.13.3`: Permission independent git ownership (before you had to make sure git folder matches running user in container to not get an git error like "dubious ownership"). | ================================================ FILE: docs/docs/configuration/scheduled.md ================================================ --- sidebar_position: 5 title: Scheduling description: "How to run configarr regulary/schedueld" keywords: [configarr configuration, schedule, scheduler, regular, cron] --- # Scheduling configarr This section describes how you could run configarr in a scheduled manner. Depending on your used deployment or third party ([check](../installation/third-party.md)) you can have different methods for running in schedule. :::info Configarr does not support scheduled execution inside the container and most likely never will. Scheduling functionalities should be something which is handled outside of the container and something which should be bundled inside each app. ::: ## Kubernetes Kubernetes support for scheduling jobs is straigthforward. We have explicit resources for this tasks: `CronJobs` See [Kubernetes Setup](/docs/installation/kubernetes) for more information. ## Docker For docker and docker-compose we do not have explicit functionalities. Therefore we have to create our own scheduled tasks. There are different ways we could achieve this: - default cron scheduler on linux systems - running scheduler containers which executes other docker containers We have create examples for how to run the container based solutions. Check [examples/scheduled](/docs/examples#scheduled-example) for more information. ================================================ FILE: docs/docs/configuration/telemetry.md ================================================ --- sidebar_position: 5 title: Telemetry description: "Learn about Configarr's anonymous telemetry and how it helps improve the project." keywords: [telemetry, analytics, privacy, opt-in, feature usage] --- import Admonition from "@theme/Admonition"; # Telemetry 1.16.0 Configarr includes an **optional, anonymous telemetry system** that helps us understand how the application is being used. This data allows us to make better decisions about feature development, bug fixes, and overall project direction. **Telemetry is completely disabled by default.** You must explicitly opt-in to participate. No data is collected unless you enable it. ## What Data Is Collected? If you're enjoying Configarr and want to help make it even better, please consider enabling telemetry. Your participation helps ensure the project continues to evolve in ways that benefit the community! 🙏 When enabled, Configarr collects **anonymous, aggregated usage statistics** that include: ### Feature Usage - Which Arr applications are being configured (Sonarr, Radarr, etc.) - Which features are actively used: - Custom format groups and scoring - Quality definitions and profiles - Media management and naming settings - Delay profiles and root folder management - Template sources (Recyclarr vs TRaSH-Guide vs local) ### Instance Statistics - Number of configured instances per Arr type - Whether instances are enabled or disabled - Template usage counts by source ### Technical Information - Configarr version number - No personal information, API keys, or configuration details - **No personal data**: usernames, emails, IP addresses, or any identifying information - **No configuration details**: API keys, server URLs, custom format names, or file paths - **No sensitive data**: passwords, secrets, or any configuration values - **No usage patterns**: when you run Configarr or how often ## Why Telemetry? Telemetry helps us: 1. **Prioritize development** - Understand which features are most valuable to users 2. **Identify issues** - Detect problems with specific configurations or features 3. **Guide decisions** - Make informed choices about new features and improvements 4. **Improve stability** - Focus testing and bug fixes on commonly used features ## How to Enable Telemetry ### Option 1: Config File (Recommended) Add the following to your `config.yml`: ```yaml # Enable anonymous telemetry to help improve Configarr telemetry: true ``` ### Option 2: Environment Variable Set the environment variable: ```bash export TELEMETRY_ENABLED=true ``` The environment variable `TELEMETRY_ENABLED` takes precedence over the config file setting if both are specified. ## How It Works - Data is sent **anonymously** to our analytics service - Collection happens **once per run** after configuration parsing - Uses industry-standard privacy practices - When enabled, you'll see a log message: `"Telemetry enabled - Thank you for helping improve Configarr!"` - You can disable it at any time by removing the setting ## Example Configuration ```yaml title="config.yml" # Your normal configuration sonarr: instance1: base_url: http://sonarr:8989 api_key: !secret SONARR_API_KEY # Enable telemetry (optional) telemetry: true ``` ## Opting Out Telemetry is **disabled by default**. If you have it enabled and want to disable it: - Remove `telemetry: true` from your config file, or - Set `telemetry: false`, or - Remove/unset the `TELEMETRY_ENABLED` environment variable ## Questions? If you have questions about telemetry or privacy: - Check our [FAQ](../faq.md) for common questions - Review the [source code](https://github.com/raydak-labs/configarr/tree/main/src/telemetry.ts) to see exactly what data is collected - Open an issue on [GitHub](https://github.com/raydak-labs/configarr/issues) if you have concerns --- ================================================ FILE: docs/docs/examples.md ================================================ --- sidebar_position: 6 description: "Examples of Configarr usage and configuration" keywords: [configarr, examples, configuration, sonarr, radarr] --- # HowTo / Examples ## How To's ### Implementation of TRaSH-Guide Profiles **Q: I want to implement the German Radarr Profile** Let's say we want to implement the German Profile for Radarr. Visit the [TRaSH-Guide page](https://trash-guides.info/Radarr/radarr-setup-quality-profiles-german-en/) and read through the requirements. Some parts have to be done via UI like configuring naming, repacks/proper etc. Once those parts are done, we can start with the Custom Formats and QualityProfiles. For this approach, we can do 3 different things:
Use existing TRaSH-Guide profile TRaSH-Guide provides predefined profiles via JSON for [Radarr](https://github.com/TRaSH-Guides/Guides/tree/master/docs/json/radarr/quality-profiles) and [Sonarr](https://github.com/TRaSH-Guides/Guides/tree/master/docs/json/sonarr/quality-profiles) in the Github Repository. To load QualityProfiles from TRaSH-Guide, use the `trash_id` defined in the profile and specify `source` as `TRASH` in the config. In this example, we want `german-hd-bluray-web.json` ```yml title="config.yml" # ... radarr: instance1: # ... include: - template: 2b90e905c99490edc7c7a5787443748b source: TRASH ``` And that's it. Now you can adjust custom formats if needed. ```yml title="config.yml" # ... radarr: instance1: # ... custom_formats: - trash_ids: - 3bc8df3a71baaac60a31ef696ea72d36 assign_scores_to: - name: "[German] HD Bluray + WEB" score: 400 ```
Use existing Recyclarr templates You can use existing Recyclarr templates if available. Check the [Recyclarr Wiki](https://recyclarr.dev/wiki/guide-configs/) or [Github Repository](https://github.com/recyclarr/config-templates/tree/master/radarr). Two possibility here: 1. Copy & paste the provided template from the wiki 2. use only the templates (if templates for everything are provided. Must be in the includes dir.) (Hint: the value in the template field is the file name of the Recyclarr template without the extension) 1. For this example, we try to implement `German HD Bluray + WEB`. ```yml title="copy&paste" # ...existing code... radarr: hd-bluray-web-ger: # ... include: - template: radarr-quality-definition-movie - template: radarr-custom-formats-hd-bluray-web-german - template: radarr-quality-profile-hd-bluray-web-german quality_profiles: - name: HD Bluray + WEB (GER) # min_format_score: 10000 # Uncomment this line to skip English Releases custom_formats: ### Optional - trash_ids: # - b6832f586342ef70d9c128d40c07b872 # Bad Dual Groups # - 90cedc1fea7ea5d11298bebd3d1d3223 # EVO (no WEBDL) # - ae9b7c9ebde1f3bd336a8cbd1ec4c5e5 # No-RlsGroup # - 7357cf5161efbf8c4d5d0c30b4815ee2 # Obfuscated # - 5c44f52a8714fdd79bb4d98e2673be1f # Retags # - f537cf427b64c38c8e36298f657e4828 # Scene assign_scores_to: - name: HD Bluray + WEB (GER) ### Movie Versions - trash_ids: # Uncomment any of the following lines to prefer these movie versions # - 570bc9ebecd92723d2d21500f4be314c # Remaster # - eca37840c13c6ef2dd0262b141a5482f # 4K Remaster # - e0c07d59beb37348e975a930d5e50319 # Criterion Collection # - 9d27d9d2181838f76dee150882bdc58c # Masters of Cinema # - db9b4c4b53d312a3ca5f1378f6440fc9 # Vinegar Syndrome # - 957d0f44b592285f26449575e8b1167e # Special Edition # - eecf3a857724171f968a66cb5719e152 # IMAX # - 9f6cbff8cfe4ebbc1bde14c7b7bec0de # IMAX Enhanced assign_scores_to: - name: HD Bluray + WEB (GER) ### Others - trash_ids: # - 839bea857ed2c0a8e084f3cbdbd65ecb # Uncomment this line to allow HDR/DV x265 HD releases assign_scores_to: - name: HD Bluray + WEB (GER) - trash_ids: # - dc98083864ea246d05a42df0d05f81cc # Uncomment this line to allow any x265 HD releases # - e6886871085226c3da1830830146846c # Uncomment this line to allow Generated Dynamic HDR assign_scores_to: - name: HD Bluray + WEB (GER) score: 0 ``` 2. For this example, we try to implement `HD Bluray + WEB`. ```yml title="only templates" # ...existing code... radarr: hd-bluray-web-ger: # ... include: - template: radarr-quality-definition-movie - template: radarr-custom-formats-hd-bluray-web - template: radarr-quality-profile-hd-bluray-web ```
Write your own profiles Instead of using existing templates, you can create them yourself and use custom formats from TRaSH (or define your own if required, see [CustomFormatDefinition](./configuration/config-file.md)). As a starting point, you can use templates from Recyclarr and modify them as required. [Recyclarr Github](https://github.com/recyclarr/config-templates/tree/master/radarr). For this example, we try to implement an `Anime` profile. Check every dir from the includes for anime-related content: CustomFormats, Definition, and Profile. Copy those into the config. ```yml # ...existing code... radarr: instance1: custom_formats: # Scores from TRaSH json - trash_ids: # Anime CF/Scoring - fb3ccc5d5cc8f77c9055d4cb4561dded # Anime BD Tier 01 (Top SeaDex Muxers) - 66926c8fa9312bc74ab71bf69aae4f4a # Anime BD Tier 02 (SeaDex Muxers) - fa857662bad28d5ff21a6e611869a0ff # Anime BD Tier 03 (SeaDex Muxers) - f262f1299d99b1a2263375e8fa2ddbb3 # Anime BD Tier 04 (SeaDex Muxers) - ca864ed93c7b431150cc6748dc34875d # Anime BD Tier 05 (Remuxes) - 9dce189b960fddf47891b7484ee886ca # Anime BD Tier 06 (FanSubs) - 1ef101b3a82646b40e0cab7fc92cd896 # Anime BD Tier 07 (P2P/Scene) - 6115ccd6640b978234cc47f2c1f2cadc # Anime BD Tier 08 (Mini Encodes) - 8167cffba4febfb9a6988ef24f274e7e # Anime Web Tier 01 (Muxers) - 8526c54e36b4962d340fce52ef030e76 # Anime Web Tier 02 (Top FanSubs) - de41e72708d2c856fa261094c85e965d # Anime Web Tier 03 (Official Subs) - 9edaeee9ea3bcd585da9b7c0ac3fc54f # Anime Web Tier 04 (Official Subs) - 22d953bbe897857b517928f3652b8dd3 # Anime Web Tier 05 (FanSubs) - a786fbc0eae05afe3bb51aee3c83a9d4 # Anime Web Tier 06 (FanSubs) - b0fdc5897f68c9a68c70c25169f77447 # Anime LQ Groups - c259005cbaeb5ab44c06eddb4751e70c # v0 - 5f400539421b8fcf71d51e6384434573 # v1 - 3df5e6dfef4b09bb6002f732bed5b774 # v2 - db92c27ba606996b146b57fbe6d09186 # v3 - d4e5e842fad129a3c097bdb2d20d31a0 # v4 - 06b6542a47037d1e33b15aa3677c2365 # Anime Raws - 9172b2f683f6223e3a1846427b417a3d # VOSTFR - b23eae459cc960816f2d6ba84af45055 # Dubs Only # Anime Streaming Services - 60f6d50cbd3cfc3e9a8c00e3a30c3114 # VRV # Main Guide Remux Tier Scoring - 3a3ff47579026e76d6504ebea39390de # Remux Tier 01 - 9f98181fe5a3fbeb0cc29340da2a468a # Remux Tier 02 - 8baaf0b3142bf4d94c42a724f034e27a # Remux Tier 03 # Main Guide WEB Tier Scoring - c20f169ef63c5f40c2def54abaf4438e # WEB Tier 01 - 403816d65392c79236dcb6dd591aeda4 # WEB Tier 02 - af94e0fe497124d1f9ce732069ec8c3b # WEB Tier 03 assign_scores_to: - name: Anime # if no anime use default quality_definition: type: movie quality_profiles: - name: Anime reset_unmatched_scores: enabled: true upgrade: allowed: true until_quality: Remux-1080p until_score: 10000 min_format_score: 100 score_set: anime-radarr quality_sort: top qualities: - name: Remux-1080p qualities: - Bluray-1080p - Remux-1080p - name: WEB 1080p qualities: - WEBDL-1080p - WEBRip-1080p - HDTV-1080p - name: Bluray-720p - name: WEB 720p qualities: - WEBDL-720p - WEBRip-720p - HDTV-720p - name: Bluray-576p - name: Bluray-480p - name: WEB 480p qualities: - WEBDL-480p - WEBRip-480p - name: DVD - name: SDTV ```
### Adjusting provided templates by TRaSH-Guides/Recyclarr It is common to use existing templates from TRaSH-Guides or Recyclarr and modify them with either your own scores or additional custom formats. Configarr supports both use cases and allows adding custom formats when needed. ```yaml # Define a new custom format (can also be done via file) customFormatDefinitions: - trash_id: example-in-config-cf trash_scores: default: 10000 trash_description: "Language: German Only" name: "Language: Not German" includeCustomFormatWhenRenaming: false specifications: - name: Not German Language implementation: LanguageSpecification negate: true required: false fields: value: 4 sonarr: instance1: base_url: !secret sonarr_url api_key: !secret sonarr_apikey include: # Use existing templates from Recyclarr as base - template: sonarr-quality-definition-series - template: sonarr-v4-quality-profile-web-1080p - template: sonarr-v4-custom-formats-web-1080p # HINT: To use TRaSH-Guides templates, you can use them too #- template: d1498e7d189fbe6c7110ceaabb7473e6 # source: TRASH # RECYCLARR (default) or TRASH # Adjust the custom formats as needed per profile custom_formats: - trash_ids: - example-in-config-cf quality_profiles: - name: WEB-1080p # name must match with given profiles (found in Recyclarr or TRaSH-Guides) # score: 0 # Uncomment this line to add custom scoring # Overwrite existing scores - trash_ids: - e6258996055b9fbab7e9cb2f75819294 # WEB Tier 01 quality_profiles: - name: WEB-1080p # name must match with given profiles (found in Recyclarr or TRaSH-Guides) score: 123 ``` ### Using templates from TRaSH-Guides/Recyclarr but different names - renaming quality profiles. How to implement see here: [Renaming Feature](./configuration/config-file.md#quality-profile-rename) - cloning quality profiles. How to implement see here: [Cloning Feature](./configuration/config-file.md#quality-profile-clone) - duplicate templates: You can copy those templates and paste them into a locally mounted folder. Then you can rename them in the templates as required. ```yaml # The path in the container for your templates for copy & paste templates with slight modifications in the files. localConfigTemplatesPath: /app/templates sonarr: instance1: base_url: !secret sonarr_url api_key: !secret sonarr_apikey include: # Assuming we copied 3 templates for quality definition, profile, and formats to those file names (file ending .yml) - template: my-local-quality-definition-series - template: my-local-quality-profile - template: my-local-custom-formats # HINT: To use TRaSH-Guides templates, you can use them too #- template: d1498e7d189fbe6c7110ceaabb7473e6 # source: TRASH # RECYCLARR (default) or TRASH # Adjust the custom formats as needed per profile custom_formats: # Overwrite existing scores - trash_ids: - e6258996055b9fbab7e9cb2f75819294 # WEB Tier 01 quality_profiles: - name: MyLocalProfile # name must match with given profiles (found in Recyclarr or TRaSH-Guides) score: 123 ``` ## Code Examples ### Full Example A complete example demonstrating all Configarr features is available in our GitHub repository. This example includes: - Docker Compose configuration - Complete Sonarr and Radarr setup - Custom format configurations - Quality profile settings - Template usage You can find the full example at: [configarr/examples/full](https://github.com/raydak-labs/configarr/tree/main/examples/full) #### Quick Start with the Full Example 1. Start the Arr containers: ```bash docker-compose up -d ``` This will: - Create required networks - Launch \*Arr instances - Configure API keys using provided XML configs 2. Run Configarr: ```bash docker-compose -f docker-compose.jobs.yml run --rm configarr ``` #### Access Points Once running, you can access the services at: - Sonarr: http://localhost:6500 - Radarr: http://localhost:6501 - Other instances check `docker-compose.yml` #### Cleanup To remove all containers and volumes: ```bash docker-compose down -v ``` ### Scheduled Example This is an example of how to execute Configarr in a scheduled manner. You can find the full example at: [configarr/examples/scheduled](https://github.com/raydak-labs/configarr/tree/main/examples/scheduled) Please check the documentation for how to configure and use the variants. ### Store execution logs You can run configarr in different environments and different toolings which do or do not provide logging out of the box. - If you are running with kubernetes Jobs you can keep the last `x` Job logs and therefore keep the logs of the executions easily. - If you are running with the scheduler `ofelia` there the logs are also persistet in the ofelia job logs. - If you are running just from docker logs can get lost. So we provide some examples how you can store them in files: - `Cron`: If you are running with cron in theory all logs are stored somewhere in cron. But we can also redirect runs into files and keep them persistent: ```sh # Assuming you are in the folder with a configured compose. Redirect error logs and normal logs docker compose run --rm configarr >> configarr.log 2>&1 # truncating file to last 1000 lines tail -n 1000 configarr.log > configarr.log.new rm configarr.log mv configarr.log.new configarr.log ``` ================================================ FILE: docs/docs/faq.md ================================================ --- sidebar_position: 7 description: "FAQ for configarr and common problems" keywords: [configarr, faq, troubleshoot] --- # FAQ Sometimes, you might encounter unexpected errors. Before reporting an issue, please try the following steps: ## Fresh Install If you're experiencing strange issues, a fresh install can often resolve them. This involves removing existing data and caches. - remove all folders (what you have defined in your compose or depending on your setup) - rerun Configarr which recreates cache folders and more ## Custom TRaSH-Guide or Recyclarr Template URLs If you have configured a custom `trashGuideUrl` or `recyclarrUrl`, caching issues might occur. In this case, clearing the cache folders is recommended. - remove the folders for the caches - rerun Configarr ## Error: "Recv failure: Connection reset by peer" If you see an error like: ``` GitResponseError: unable to access 'https://github.com/recyclarr/config-templates/': Recv failure: Connection reset by peer ``` This can be caused by Docker bridge network issues, especially with DNS, TLS, or MTU settings. The problem may only occur when using Docker's default bridge network, and not with `network_mode: host`. Reference issues: - https://github.com/raydak-labs/configarr/issues/300 (thanks for @jtnqr for helping trouble shooting) ### Troubleshooting Steps - Try running Configarr with `network_mode: host` in your Docker Compose file. This often resolves the issue immediately. - Check your DNS and MTU settings if you use custom networking (VPN, Pi-hole, etc.). - If you have a VPN or custom DNS setup, try disabling them temporarily to see if the problem persists. - You can also manually clone the repo inside the container to verify if plain `git` works: ```sh docker exec -it sh git clone https://github.com/recyclarr/config-templates/ # also check git pull ``` ### Example Docker Compose workaround ```yaml services: configarr: network_mode: host # ...other options ``` > **Note:** Using `network_mode: host` is generally safe for Configarr, as it does not expose ports by default. However, be aware of your environment's security requirements. ## DNS Resolution Problems (Could not resolve host: github.com) If you encounter errors like: ``` GitError: Cloning into '/app/repos/trash-guides'... fatal: unable to access 'https://github.com/TRaSH-Guides/Guides/': Could not resolve host: github.com ``` This is usually caused by DNS issues inside the Docker container. Even if DNS works on your host and inside the container when tested manually, the error may still occur intermittently for git operations. ### Troubleshooting Steps - Test DNS resolution inside the container: ```sh docker run --rm -it busybox nslookup github.com ``` - Try changing your DNS server to a public DNS (e.g., 1.1.1.1 or 8.8.8.8) on your host or in your Docker configuration. - Avoid using ISP DNS servers, as they may cause intermittent failures. - Restart the container after changing DNS settings. - If you use custom Docker networks, test with the default bridge or host network. Reference issues: - https://github.com/raydak-labs/configarr/issues/266 - https://github.com/raydak-labs/configarr/issues/188 ## Git Clone Errors with Legacy Kernels If you encounter errors like: ``` Error: Unable to checkout revision 'master' from 'https://github.com/recyclarr/config-templates'. The revision may not exist in the repository. Error: index-pack failed ``` or ``` Function not implemented ``` This can be caused by legacy kernels that don't support modern git clone options like `--filter=blob:none` or sparse checkout features. ### Solution Set the `CONFIGARR_DISABLE_GIT_CLONE_OPTIONS` environment variable to disable these advanced git clone options: **Docker Compose:** ```yaml services: configarr: environment: - CONFIGARR_DISABLE_GIT_CLONE_OPTIONS=1 # ...other options ``` **Docker run:** ```bash docker run -e CONFIGARR_DISABLE_GIT_CLONE_OPTIONS=1 ... ``` **Kubernetes:** ```yaml env: - name: CONFIGARR_DISABLE_GIT_CLONE_OPTIONS value: "1" ``` When this variable is set, Configarr will perform standard git clones without the `--filter=blob:none` or `--sparse` options, which should work with older kernel versions. If your kernel is very old and the error still happens (for example `unable to get random bytes for temporary file: Function not implemented`), use the `alpine3.22` image tag which pins the Alpine base for compatibility: ```yaml services: configarr: image: ghcr.io/raydak-labs/configarr:-alpine3.22 ``` Example: ```yaml image: ghcr.io/raydak-labs/configarr:v1.24.0-alpine3.22 ``` Reference issues: - https://github.com/raydak-labs/configarr/issues/367 ## TRaSH-Guides Breaking Changes (Feb 2026) {#trash-guides-breaking-changes-2026-02} :::warning Breaking Change TRaSH-Guides made significant changes to their JSON structure in February 2026. This affects both CF group semantics and quality profile ordering. ::: **Commit:** [2994a7979d8036a7908a92e2cd286054fd4fcc1b](https://github.com/TRaSH-Guides/Guides/commit/2994a7979d8036a7908a92e2cd286054fd4fcc1b) ### What Changed **1. CF Groups: `exclude` → `include` semantics** ```json // OLD: CFs applied to ALL profiles EXCEPT listed ones "quality_profiles": { "exclude": { "HD Bluray + WEB": "..." } } // NEW: CFs applied ONLY to listed profiles "quality_profiles": { "include": { "Remux + WEB 1080p": "..." } } ``` **2. Quality Profile Items: API order → Display order** - **Before**: Quality items in API response order (internal) - **After**: Quality items in display order (highest-to-lowest priority) ### Backward Compatibility **Option 1: Pin to TRaSH-Guides revision (recommended for stability)** For Configarr versions **< 1.22.0**, pin to the last commit before the changes: ```yaml # config.yml trashRevision: d2105f2e1b04c7e30ae44e73d682298609438216 ``` This uses the old TRaSH-Guides structure without needing the compatibility flag. **Option 2: Use compatibility flag (Configarr >= 1.22.0)** For Configarr versions **>= 1.22.0**, use the new TRaSH-Guides structure with the compatibility flag if needed: ```yaml # config.yml # Enable for old TRaSH-Guides behavior (before Feb 2026) compatibilityTrashGuide20260219Enabled: true ``` | Setting | CF Groups | Quality Ordering | | ----------------- | ------------------- | --------------------------- | | `false` (default) | `include` semantics | Display order (no reversal) | | `true` | `exclude` semantics | API order (with reversal) | :::info Temporary Flag The `compatibilityTrashGuide20260219Enabled` flag is **temporary** and will be removed in a future version. It's recommended to update to the latest TRaSH-Guides version. ::: ### Version Matrix | Configarr Version | TRaSH-Guides Default | Old Behavior Via | | ----------------- | -------------------- | ----------------------------------------------------------------------------------------------------------- | | < 1.22.0 | Old structure | N/A (default) | | >= 1.22.0 | New structure | `compatibilityTrashGuide20260219Enabled: true` OR `trashRevision: d2105f2e1b04c7e30ae44e73d682298609438216` | ================================================ FILE: docs/docs/installation/_category_.json ================================================ { "label": "Installation", "position": 3, "link": { "type": "generated-index", "description": "Learn how to install Configarr" } } ================================================ FILE: docs/docs/installation/_include/docker-basic-conf.yml ================================================ #trashGuideUrl: https://github.com/BlackDark/fork-TRASH-Guides #recyclarrConfigUrl: https://github.com/BlackDark/fork-recyclarr-configs localCustomFormatsPath: /app/cfs localConfigTemplatesPath: /app/templates customFormatDefinitions: - trash_id: example-in-config-cf trash_scores: default: -10000 trash_description: "Language: German Only" name: "Language: Not German" includeCustomFormatWhenRenaming: false specifications: - name: Not German Language implementation: LanguageSpecification negate: true required: false fields: value: 4 sonarr: instance1: # Set the URL/API Key to your actual instance base_url: http://sonarr:8989 api_key: !secret SONARR_API_KEY quality_definition: type: series include: #### Custom - template: sonarr-cf # template name - template: sonarr-quality custom_formats: # Movie Versions - trash_ids: - 9f6cbff8cfe4ebbc1bde14c7b7bec0de # IMAX Enhanced quality_profiles: - name: ExampleProfile # score: 0 # Uncomment this line to disable prioritised IMAX Enhanced releases radarr: {} # no radarr instance ================================================ FILE: docs/docs/installation/binary.md ================================================ --- sidebar_position: 4 title: Binary description: "Run configarr as binary file" keywords: [configarr binary, configarr executable] --- import Admonition from "@theme/Admonition"; import CodeBlock from "@theme/CodeBlock"; import DockerBasicConf from "!!raw-loader!./\_include/docker-basic-conf.yml"; # Executable / Binary 1.17.0 With 1.17.0 we have started to distribute configarr additionally as binary files. This is currently based on [Bun Compilation](https://bun.com/docs/bundler/executables) If you have problems or feedback feel free to create an issue to discuss potential problems or optimizations. ## Quick Start Checkout the releases in [Github](https://github.com/raydak-labs/configarr/releases/). There we will attach binaries for different architectures and systems. The files are probably compressed and need to be extracted. Afterwards you can run the executable as any other program or tool. Need more help? [open an issue](https://github.com/raydak-labs/configarr/issues). ## FAQ - `On MacOS if I download files the file is corrupt`: If downloaded via browser or something the resulting executable can be quarantined. - To check attributes: `xattr ./configarr -l` - To remove quarantine: `xattr -dr com.apple.quarantine ./configarr` ================================================ FILE: docs/docs/installation/docker.md ================================================ --- sidebar_position: 1 title: Docker Installation description: "Learn how to install and configure Configarr using Docker" keywords: [configarr docker, docker installation, docker setup, configarr configuration] --- import CodeBlock from "@theme/CodeBlock"; import DockerBasicConf from "!!raw-loader!./\_include/docker-basic-conf.yml"; # Docker Installation This guide will walk you through setting up Configarr using Docker. :::tip For quick starting and testing you can use the `latest` tag. But if you are ready and finished switch to fixed tag like `1.9.0` so you can update and do required changes if we release new versions. Solutions like `Renovate` are good for keeping your dependencies updated. ::: ## Quick Start The fastest way to get started is using the official Docker image: ```bash title="shell" docker run -d \ --name=configarr \ -v /path/to/config:/config \ ghcr.io/raydak-labs/configarr:latest # Or use dockerhub image: docker run -d \ --name=configarr \ -v /path/to/config:/config \ configarr/configarr:latest ``` ## Docker Compose (Recommended) For a more maintainable setup, we recommend using Docker Compose: ```yaml title="compose.yml" #version: "3.8" services: configarr: image: ghcr.io/raydak-labs/configarr:latest container_name: configarr #user: 1000:1000 # Optional, defaults to root:root environment: - TZ=Etc/UTC volumes: - ./config:/app/config # Contains the config.yml and secrets.yml - ./dockerrepos:/app/repos # Cache repositories - ./custom/cfs:/app/cfs # Optional if custom formats locally provided - ./custom/templates:/app/templates # Optional if custom templates # restart: "no" # optional make sure this is set to no or removed. Default is no ``` Save this as `docker-compose.yml` and run: ```bash title="shell" docker-compose run --rm configarr ``` ## Configuration ### Volume Mappings | Volume | Description | | ---------------- | ------------------------------------------------------------------------------------- | | `/app/config` | Contains all configuration files and data. Can be changed with Environment Variables. | | `/app/repos` | Contains cached repos. Can be changed with Environment Variables. | | `/app/cfs` | Contains custom cfs. Can be changed with Environment Variables. | | `/app/templates` | Contains templates. Can be changed with Environment Variables. | ### Environment Variables See [Environment Variables](../configuration/environment-variables.md) ## Basic Configuration Create a configuration file at `/path/to/config/config.yml` more information about the config file can be found [here](../configuration/config-file.md). You can also test everything with the [Full Example](../examples.md) locally.
Very basic configuration {DockerBasicConf}
## Updating To update to the latest version: ```bash title="shell" docker-compose pull docker-compose run --rm configarr ``` ## Troubleshooting Running the container will output logs to the console. With those you can see what is happening and if there are any issues. Increase the log level with the `LOG_LEVEL` environment variable to get more detailed logs. ### Common Issues - **Permission Issues** - Ensure user matches your required user - Check folder permissions on the config directory - after changing the user, adjust the user in the git repos (TRaSH-Guides, recyclarr) to match - **Connection Issues** - Verify Sonarr/Radarr URLs are accessible from the container - Confirm API keys are correct - Check network connectivity between containers if using Docker networks - **Configuration Issues** - Validate your YAML syntax - Ensure all required fields are present in config.yaml - **Container restarting** - Ensure you have not set restart policies and running with `docker-compose up -d`. This triggers the docker daemon to restart the container every minute. - Scheduling is NOT implemented into configarr as described [here](../configuration/scheduled.md). Therefore please check the [Scheduled example](../examples.md) Need more help? [open an issue](https://github.com/raydak-labs/configarr/issues). ================================================ FILE: docs/docs/installation/kubernetes.md ================================================ --- sidebar_position: 2 title: Kubernetes Installation description: "Learn how to install and configure Configarr using Kubernetes" keywords: [configarr kubernetes, kubernetes installation, kubernetes setup, configarr configuration] --- # Kubernetes Installation Guide This guide will help you deploy Configarr in a Kubernetes environment. Configarr can be run as a CronJob to periodically sync your configurations. ## Prerequisites - A working Kubernetes cluster - `kubectl` configured to access your cluster - Basic understanding of Kubernetes resources (ConfigMaps, Secrets, CronJobs) ## Installation Steps ### 1. Create the Configuration Files First, create `config.yml` and choose how to provide sensitive values: - `config.yml` - Your main Configarr configuration (required) - Environment variables via Kubernetes `Secret` + `!env` in `config.yml` (recommended) - `secrets.yml` + `!secret` in `config.yml` (optional alternative) For detailed configuration options, see the [Configuration Guide](../configuration/config-file.md). ### 2. Deploy to Kubernetes Below is a complete example of the necessary Kubernetes resources. Save this as `configarr.yaml`: ```yaml title="configarr.yaml" --- apiVersion: batch/v1 kind: CronJob metadata: name: configarr spec: schedule: "0 * * * *" # Runs every hour successfulJobsHistoryLimit: 1 failedJobsHistoryLimit: 1 jobTemplate: spec: template: spec: containers: - name: configarr image: ghcr.io/raydak-labs/configarr:latest imagePullPolicy: Always tty: true # for color support envFrom: - configMapRef: name: common-deployment-environment - secretRef: name: configarr-env volumeMounts: - mountPath: /app/repos # Cache repositories name: app-data subPath: configarr-repos - name: config-volume # Mount specific config mountPath: /app/config/config.yml subPath: config.yml volumes: - name: app-data persistentVolumeClaim: claimName: media-app-data - name: config-volume configMap: name: configarr restartPolicy: Never --- apiVersion: v1 kind: Secret metadata: name: configarr-env type: Opaque stringData: SONARR_API_KEY: "your-sonarr-api-key-here" --- apiVersion: v1 kind: ConfigMap metadata: name: configarr data: config.yml: | trashGuideUrl: https://github.com/TRaSH-Guides/Guides recyclarrConfigUrl: https://github.com/recyclarr/config-templates sonarr: series: base_url: http://sonarr:8989 api_key: !env SONARR_API_KEY quality_definition: type: series include: # WEB-1080p - template: sonarr-quality-definition-series - template: sonarr-v4-quality-profile-web-1080p - template: sonarr-v4-custom-formats-web-1080p # WEB-2160p - template: sonarr-v4-quality-profile-web-2160p - template: sonarr-v4-custom-formats-web-2160p custom_formats: [] radarr: {} ``` ### 3. Deploy the Resources Apply the configuration to your cluster: ```bash title="shell" kubectl apply -f configarr.yaml ``` ## Configuration Details ### CronJob Configuration - `schedule`: Set how often Configarr should run (default: hourly) - `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`: Control how many completed/failed jobs to keep ### Volume Mounts 1. **Repository Cache** (`/app/repos`): - Persists downloaded repositories to avoid repeated downloads - Requires a PersistentVolumeClaim 2. **Configuration** (`/app/config/config.yml`): - Main configuration file mounted from ConfigMap - See [Configuration Guide](../configuration/config-file.md) for options 3. **Environment Variables** (`envFrom.secretRef`): - Sensitive data loaded from Kubernetes Secret - Referenced with `!env` in `config.yml` - Avoids duplicating API keys in both Kubernetes Secrets and a mounted `secrets.yml` ### Security Considerations - Store sensitive information in Kubernetes Secrets - Use `!env` in `config.yml` to read values injected from Kubernetes Secrets - If you prefer mounted secret files, `!secret` with `secrets.yml` is still supported - Consider using sealed secrets or external secret management solutions ## Alternative Deployment Options If Kubernetes is not suitable for your environment, consider: - [Docker Installation](docker.md) for simpler containerized deployment - Running directly on the host system ## Troubleshooting 1. Check the CronJob logs: ```bash kubectl get pods | grep configarr kubectl logs ``` 2. Verify your secret-backed environment variables are present: ```bash kubectl describe pod ``` 3. Ensure your PersistentVolumeClaim is bound: ```bash kubectl get pvc ``` For more detailed configuration options, refer to the [Configuration Guide](../configuration/config-file.md). ================================================ FILE: docs/docs/installation/third-party.md ================================================ --- sidebar_position: 3 title: Third party description: "Learn how to install and configure Configarr in third party services." keywords: [configarr docker, docker installation, docker setup, unraid] --- # Third partys This guide will walk you through setting up Configarr in 3rd party services. :::tip As this is new and you are missing some services feel free to create a PR! Contributions welcome! ::: ## Proxmox VE Helper-Scripts
Logo from Proxmox Helper Scripts
Thanks to Community User @finkerle we have now an installation script for Proxmox users! With the script you can install & update the configarr version in your proxmox instance automatically. The instance will be deployed as an LXC Container. Check it out here [Configarr Proxmox Helper](https://community-scripts.github.io/ProxmoxVE/scripts?id=configarr). ## Unraid {#unraid} :::tip Existing apps in Unraid CA are not maintained by us! If donating it is not directed to us! Please check configarr Github pages if you want to donate. Contributions welcome! ::: Setting up in Unraid with docker is straigth forward and combined with `ofelia` we can schedule the containers easily. _HINT_: The provided Apps in Unraid are not maintained by us! Make sure to enable Advanced/extended view in Unraid (top right). - Configarr: ``` Name: configarr (we need this later on) Repository: configarr/configarr:latest # Recommendation: use tags like 1.9.0 (add volume mappings like your setups requires it. Example with - :) Config volume - /mnt/user/appdata/configarr/config:/app/config Repo cache - /mnt/user/appdata/configarr/repos:/app/repos Custom formats - /mnt/user/appdata/configarr/cfs:/app/cfs Templates - /mnt/user/appdata/configarr/templates:/app/templates ``` - Add other variables or mapping as your setup requires it - Afterwards create the required files in the config volume `config.yml` and `secrets.yml` (check examples or this guide) - Ofelia (scheduler): ``` Name: ofelia Repository: mcuadros/ofelia:latest # Recommendation: use specific tags not latest Post Arguments: daemon --config=/opt/config.ini (add volume mappings like your setups requires it. Example with - :) Docker socket - /var/run/docker.sock:/var/run/docker.sock (Read Only) Ofelia config file - /mnt/user/appdata/ofelia/ofelia.ini:/opt/config.ini (Read only) ``` - Make sure to create the `ofelia.ini` file best before starting the container ```ini [job-run "run-configarr-existing-container"] schedule = @every 10s # adjust as required. Recommendation every 3h or so container = configarr # this is the name of container we gave ``` - you can also activate `autostart` for ofelia ![Unraid Setup with the containers](_images/unraid_setup.webp) Now start both containers. Check the logs if configarr works as expected (exit code should be 0). Ofelia should keep running and restarting the configarr in your defined interval. **Enjoy!** ## Synology NAS {#synology} For scheduled runs on Synology you can use the [Task Scheduler](https://kb.synology.com/en-au/DSM/help/DSM/AdminCenter/system_taskscheduler?version=7) in order to run configarr in a cron way. To configure a scheduled task in DSM 7.2 you go to Control Panel - Services - Task Scheduler. From there you can create a new Scheduled Task (User-defined script). As Synology requires root permission to run docker containers, "root" should be chosen as the user. Then within the Schedule tab you can choose your preferred frequency to run configarr. For the actual user-defined script you just input the docker run command you also use in an interactive terminal, but be sure to NOT include `sudo` in your command (as your already run the command with root permissions). Like so: ``` docker run -d --rm --name=configarr -e TZ=[YOUR-TIMEZONE] -v /[SYNOLOGY-VOLUME]/[SYNOLOGY-SHARED-FOLDER-OF-YOUR-DOCKER-CONTAINERS]/[CONFIGARR-SUBFOLDER]:/app/config ghcr.io/raydak-labs/configarr:[REQUIRED-VERSION] ``` For example: ``` docker run -d --rm --name=configarr -e TZ=Europe/Amsterdam -v /volume1/docker/configarr:/app/config ghcr.io/raydak-labs/configarr:1.12.0 ``` Alternatively if you want to be able to view the logs within Synology's Container Manager after configarr has finished running, then you could remove the `--rm` flag and start the user-defined script with `docker rm configarr` so that the container is not immediately removed after it has finished running. For example: ``` docker rm configarr docker run -d --name=configarr -e TZ=Europe/Amsterdam -v /volume1/docker/configarr:/app/config ghcr.io/raydak-labs/configarr:1.12.0 ``` After clicking "OK" it will ask for your password, given that you created a scheduled script with root permissions. After you're done you can perform a run manually to check if everything works by selecting the task and press "Run". ## NixOS Module 1.18.0 {#nixos} :::warning Experimental Feature NixOS module support is experimental and available from version 1.18.0 onwards. ::: Configarr can be run as a systemd service on NixOS using the included NixOS module. ### Setup Include the configarr input in your flake: ```nix inputs.configarr.url = "github:raydak-labs/configarr"; ``` Then import the module and configure the service: ```nix { config, inputs, ... }: { imports = [ inputs.configarr.nixosModules.default ]; services.configarr = { config = # yaml '' radarr: radarr_instance: api_key: !env RADARR_API_KEY base_url: http://localhost:${toString config.services.radarr.settings.server.port} media_naming: folder: default root_folders: - /mnt/movies/English ''; enable = true; environmentFile = "${config.sops.templates.configarr-ev.path}"; }; sops = { secrets = { radarr-api-key.sopsFile = ./secrets/radarr-api-key; }; templates.configarr-ev = { content = '' LOG_LEVEL=debug LOG_STACKTRACE=true RADARR_API_KEY=${config.sops.placeholder.radarr-api-key} ''; inherit (config.services.configarr) group; owner = config.services.configarr.user; }; }; } ``` This configuration sets up configarr as a systemd service with proper secret management using sops-nix. ### Updating to a New Version To update configarr to a new version, you need to update both the version number and the corresponding hashes in the nix package file. 1. Edit `nix/package.nix` and update the `version` field to the desired release (e.g., `"1.18.0"`) 2. Update the `rev` field in `fetchFromGitHub` to match: `"v1.18.0"` 3. Set both hash fields to empty strings (`hash = "";`) 4. Run `nix build` - it will fail and provide you with the correct hashes 5. Copy the hash from the error message for `fetchFromGitHub` and update the `src.hash` field 6. Run `nix build` again - it will fail again for the pnpm dependencies 7. Copy the hash from this error message and update the `pnpmDeps.hash` field 8. Run `nix build` once more - it should now succeed Alternatively, you can find the source hash directly on GitHub: - Go to `https://github.com/raydak-labs/configarr/releases/tag/v[VERSION]` - Download the source tarball and calculate its hash using `nix hash file [downloaded-file]` ================================================ FILE: docs/docs/intro.mdx ================================================ --- sidebar_position: 1 description: "Configarr - A powerful synchronization tool for Sonarr, Radarr and other *Arr tools that helps manage custom formats and quality profiles using TRaSH-Guides and custom configurations" keywords: [ configarr, sonarr, radarr, trash guides, TRaSH-Guides, custom formats, media management, automation, recyclarr, quality profiles, whisparr, ] --- # Introduction Welcome to Configarr - your all-in-one solution for managing Sonarr and Radarr (and other \*Arr tools) configurations with seamless integration of TRaSH-Guides and custom formats. ## What is Configarr? Configarr is a powerful configuration and synchronization tool designed specifically for Sonarr v4 and Radarr v5. It streamlines the process of managing custom formats and quality profiles by automatically synchronizing settings from TRaSH-Guides while supporting additional customizations. ### Experimental support Experimental support also available for [(check experimental support)](./configuration/experimental-support.md): - Whisparr v3 - Readarr v1 - Lidarr v2 ### Key Features - 🔄 **TRaSH-Guides Integration**: Directly sync custom formats and quality profiles from TRaSH-Guides - 🔗 **Recyclarr Template Compatibility**: Works with existing Recyclarr templates - 🎯 **Custom Format Support**: Create and manage your own custom formats - 🌍 **Multi-language Support**: Includes specialized formats for different languages/countries - 🔧 **Flexible Configuration**: Multiple ways to provide custom formats: - Sync from TRaSH-Guides - Sync from local files - Direct configuration in YAML - Smart merging (TRaSH-Guide → Local Files → Config) ### Why Choose Configarr? If you're managing a media server with Sonarr and Radarr (or other \*Arr tools), Configarr helps you: - Save time by automating configuration management - Maintain consistency across your media servers - Easily implement best practices from TRaSH-Guides - Customize settings for your specific needs - We provide custom formats for different languages/countries as long as TRaSH-Guides does not include them ## Requirements - Sonarr v4 - Radarr v5 - check experimental support [here](./configuration/experimental-support.md) - Docker or Kubernetes ## Getting Started Ready to streamline your media server configuration? Let's get started with the basic setup. - [Continue to Installation →](/docs/category/installation/) - [HowTo Configuration →](./examples.md) - **[YouTube Setup Guide](https://www.youtube.com/watch?v=LoeCXCB89h0)** :::note **First** youtube video creation. If useful feel free to 🔔 ::: ### Container Images Images are available via Github Container Registry (ghcr) and dockerhub with tags and latest (check the repos for all available tags): - GHCR: https://github.com/raydak-labs/configarr/pkgs/container/configarr - `ghcr.io/raydak-labs/configarr:latest` - DockerHub: https://hub.docker.com/repository/docker/configarr/configarr/general - `docker.io/configarr/configarr:latest` or simply `configarr/configarr:latest` ### Related/Inspired Projects - [TRaSH-Guides](https://trash-guides.info/) - [Recyclarr](https://github.com/recyclarr/recyclarr) - [Notifiarr](https://notifiarr.com/) - [Profilarr](https://github.com/Dictionarry-Hub/profilarr) ## Changes / Changelog You can find the changes and new features in Github. See: - [Changelog](https://github.com/raydak-labs/configarr/blob/main/CHANGELOG.md) - or [Github Releases](https://github.com/raydak-labs/configarr/releases) :::tip New to media server management? Check out our [concepts guide](./concepts.md) to understand the basics of custom formats and quality profiles. ::: ## Star History Help us reach 1000 stars!
================================================ FILE: docs/docs/profiles/index.mdx ================================================ --- sidebar_position: 5 description: "Sample profiles" keywords: [configarr, examples, configuration, profiles] --- import CodeBlock from "@theme/CodeBlock"; # Quality Profiles Profiles you can copy and paste to use for your desired profiles. You can always modify and create own profiles just copy the existing configs as base and modify as wanted. For example you like the base for the german custom formats: - you can either just adjust scorings for specific custom formats - or you can copy everything as base and maintain the scores without the need of a forked templates repo :::tip If you are starting to setup probably start taking a look at [HowTos](../examples) ::: ## From scratch {#from-scratch} You can start to implement and share full profiles directly in the config + custom formats. Everything can be done directly in your configuration without the need to fork or maintain repository. See a quick example [here](https://gist.github.com/BlackDark/19e0c10422d7178c9e1ef1dd52a5aa70) for defining everything a profile needs ## Existing base templates You can use existing base templates (configuration files): - TRaSH - using with `includes` - Recyclarr - using with `includes` (matching includes folder) - or copy&paste the `templates`/`pre-built configurations`. | Source | Radarr | Sonarr | | ----------------------- | :--------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------: | | **TRaSH-Guides** | [TRaSH Radarr](https://github.com/TRaSH-Guides/Guides/tree/master/docs/json/radarr/quality-profiles) | [TRaSH Sonarr](https://github.com/TRaSH-Guides/Guides/tree/master/docs/json/sonarr/quality-profiles) | | **Recyclarr Templates** | [Recyclarr Radarr](https://github.com/recyclarr/config-templates/tree/master/radarr) | [Recyclarr Sonarr](https://github.com/recyclarr/config-templates/tree/master/sonarr) | :::note Recyclarr `includes` will be updated automatically because they are included. Recyclarr `Templates`/`Pre-Built Configuration Files` themselve _NOT_ and you have to update them if they will be changed in repository. You can mostly copy&paste the pre-built files and adjust slightly to work with configarr. ::: ## Language based We can use the existing templates provided in the TRaSH-Guides (recommended) or Recyclarr to start with a good starting base. Afterwards you can adjust scores as you need them to be or adopt the profile and customize it completely to your requirements. If you need to know how to include those templates [see here](../examples). ### English profiles | Source | Radarr | Sonarr | | ----------------------- | :-----------------------------------------------------------------------------: | :-----------------------------------------------------------------------------: | | **TRaSH-Guides** | [TRaSH Radarr](https://trash-guides.info/Radarr/radarr-setup-quality-profiles/) | [TRaSH Sonarr](https://trash-guides.info/Sonarr/sonarr-setup-quality-profiles/) | | **Recyclarr Templates** | [Recyclarr Radarr](https://recyclarr.dev/wiki/guide-configs/#hd-bluray-web) | [Recyclarr Sonarr](https://recyclarr.dev/wiki/guide-configs/#web-1080p-v4) | ### English Profiles (Anime) | Source | Radarr | Sonarr | | ----------------------- | :-----------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------: | | **TRaSH-Guides** | [TRaSH Radarr](https://trash-guides.info/Radarr/radarr-setup-quality-profiles-anime/) | [TRaSH Sonarr](https://trash-guides.info/Sonarr/sonarr-setup-quality-profiles-anime/) | | **Recyclarr Templates** | [Recyclarr Radarr](https://recyclarr.dev/wiki/guide-configs/#anime-radarr) | [Recyclarr Sonarr](https://recyclarr.dev/wiki/guide-configs/#anime-sonarr-v4) | ### German profiles | Source | Radarr | Sonarr | | ----------------------- | :---------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------: | | **TRaSH-Guides** | [TRaSH Radarr](https://trash-guides.info/Radarr/radarr-setup-quality-profiles-german-en/) | [TRaSH Sonarr](https://trash-guides.info/Sonarr/sonarr-setup-quality-profiles-german-en/) | | **Recyclarr Templates** | [Recyclarr Radarr](https://recyclarr.dev/wiki/guide-configs/#german-hd-bluray-web) | [Recyclarr Sonarr](https://recyclarr.dev/wiki/guide-configs/#german-hd-bluray-web-v4) | ### German Profiles (Anime) Currently (as of 2025-02) no finished profiles exist for German Anime formats. So you can either start with the English ones from TRaSH-Guide and modify with the German language CFs or use some existing templates from the community. Example for starting profiles from scratch [here](#from-scratch) Community configs 👥🤝🤗 : - https://github.com/nani8ot/configarr-anime - https://github.com/MajorPain007/homelab/tree/main/configarr :::note Be sure to copy all required configs and templates when using the community projects. And keep in mind that you need to keep track of possible changes on your own. ::: ## Modifications / Adjustments Please check the [Config](../configuration/config-file) for all available options. - Reference for starting full profiles from scratch: [here](#from-scratch) - Adjusting the `language` of a QualityProfile. TRaSH-Guide profiles has added support for the `language` in their provided JSON files. This will be used if available. But you can also adjust the value also in the config file. ```yaml title="config.yml" radarr: instance1: # ... quality_profiles: - name: HD Bluray + WEB # Support added with 1.7.0. Not support in all *arr applications. Check the application if it is supported. language: Any # The name must match available names in *arr ``` - Adjusting scoring for custom formats: ```yaml title="config.yml" radarr: instance1: # ... custom_formats: # Custom format assignments - trash_ids: - 9f6cbff8cfe4ebbc1bde14c7b7bec0de # Some existing CustomFormat (this is the ID from TRaSH-Guides) assign_scores_to: - name: HD Bluray + WEB # The existing or new QualityProfile Name. Must match! score: 0 # New scoring ``` ================================================ FILE: docs/docusaurus.config.ts ================================================ import type * as Preset from "@docusaurus/preset-classic"; import type { Config } from "@docusaurus/types"; import { default as lunrSearch } from "docusaurus-lunr-search"; import { themes as prismThemes } from "prism-react-renderer"; // This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) const config: Config = { title: "Configarr", tagline: "Simplified configuration management for your Arr applications like Sonarr, Radarr and more.", favicon: "img/favicon.ico", // Set the production url of your site here url: "https://configarr.de", // Set the // pathname under which your site is served // For GitHub pages deployment, it is often '//' baseUrl: "/", // GitHub pages deployment config. // If you aren't using GitHub pages, you don't need these. organizationName: "raydak-labs", // Usually your GitHub org/user name. projectName: "configarr", // Usually your repo name. onBrokenLinks: "throw", markdown: { hooks: { onBrokenMarkdownLinks: "warn", }, }, // Even if you don't use internationalization, you can use this field to set // useful metadata like html lang. For example, if your site is Chinese, you // may want to replace "en" with "zh-Hans". i18n: { defaultLocale: "en", locales: ["en"], }, presets: [ [ "classic", { docs: { sidebarPath: "./sidebars.ts", // Please change this to your repo. // Remove this to remove the "edit this page" links. editUrl: "https://github.com/raydak-labs/configarr/tree/main/docs/", }, blog: { showReadingTime: true, feedOptions: { type: ["rss", "atom"], xslt: true, }, // Please change this to your repo. // Remove this to remove the "edit this page" links. editUrl: "https://github.com/raydak-labs/configarr/tree/main/docs/", // Useful options to enforce blogging best practices onInlineTags: "warn", onInlineAuthors: "warn", onUntruncatedBlogPosts: "warn", }, theme: { customCss: "./src/css/custom.css", }, } satisfies Preset.Options, ], ], plugins: [ lunrSearch, () => ({ name: "inject-tag", injectHtmlTags() { return { headTags: [ ` `, ], }; }, }), ], themeConfig: { // Replace with your project's social card image: "img/docusaurus-social-card.jpg", colorMode: { defaultMode: "dark", }, metadata: [ { name: "description", content: "Configarr - Simplify your configuration management for Arr applications like Sonarr, Radarr, Readarr, Lidarr.", }, { name: "keywords", content: "configarr, configuration, management, automation, sonarr, radarr, lidarr, recyclarr, notifiarr" }, { name: "robots", content: "index, follow" }, { property: "og:title", content: "Configarr - Configuration Management Simplified" }, { property: "og:description", content: "Easily manage and automate your configurations in Arr (Sonarr,Radarr,Lidarr,Readarr) with Configarr.", }, ], navbar: { title: "Configarr", logo: { alt: "Configarr Logo", src: "img/logo.svg", }, items: [ { type: "docSidebar", sidebarId: "tutorialSidebar", position: "left", label: "Documentation", }, // { to: "/blog", label: "Blog", position: "left" }, { href: "https://github.com/raydak-labs/configarr", label: "GitHub", position: "right", }, { type: "html", position: "right", value: 'GitHub Repo stars', }, ], }, footer: { style: "dark", links: [ { title: "Docs", items: [ { label: "Intro", to: "/docs/intro", }, ], }, { title: "Community", items: [ { label: "German Discord (UsenetDE)", href: "https://discord.gg/Z2wTmrmFgn", }, { label: "TRaSH-Guides", href: "https://trash-guides.info/", }, // { // label: "Discord", // href: "https://discordapp.com/invite/docusaurus", // }, // { // label: "X", // href: "https://x.com/docusaurus", // }, ], }, { title: "More", items: [ // { // label: "Blog", // to: "/blog", // }, { label: "GitHub", href: "https://github.com/raydak-labs/configarr", }, { label: "Stack Overflow", href: "https://stackoverflow.com/questions/tagged/configarr", }, { label: "YouTube", href: "https://www.youtube.com/@raydak-labs", }, ], }, ], copyright: `Copyright © ${new Date().getFullYear()} Configarr. Built with Docusaurus.`, }, prism: { theme: prismThemes.github, darkTheme: prismThemes.dracula, }, } satisfies Preset.ThemeConfig, // use trailing slashes as github pages uses them, this also fixes the sitemap.xml trailingSlash: true, }; export default config; ================================================ FILE: docs/package.json ================================================ { "name": "configarr", "version": "0.0.0", "private": true, "scripts": { "docusaurus": "docusaurus", "start": "docusaurus start", "build": "docusaurus build", "swizzle": "docusaurus swizzle", "deploy": "docusaurus deploy", "clear": "docusaurus clear", "serve": "docusaurus serve", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", "typecheck": "tsc" }, "dependencies": { "@docusaurus/core": "3.9.2", "@docusaurus/preset-classic": "3.9.2", "@mdx-js/react": "3.1.1", "clsx": "2.1.1", "docusaurus-lunr-search": "3.6.1", "lunr": "2.3.9", "prism-react-renderer": "2.4.1", "raw-loader": "4.0.2", "react": "19.2.4", "react-dom": "19.2.4" }, "devDependencies": { "@docusaurus/module-type-aliases": "3.9.2", "@docusaurus/tsconfig": "3.9.2", "@docusaurus/types": "3.9.2", "typescript": "6.0.2" }, "browserslist": { "production": [ ">0.5%", "not dead", "not op_mini all" ], "development": [ "last 3 chrome version", "last 3 firefox version", "last 5 safari version" ] }, "engines": { "node": "25.9.0" } } ================================================ FILE: docs/sidebars.ts ================================================ import type { SidebarsConfig } from "@docusaurus/plugin-content-docs"; // This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) /** * Creating a sidebar enables you to: - create an ordered group of docs - render a sidebar for each doc of that group - provide next/previous navigation The sidebars can be generated from the filesystem, or explicitly defined here. Create as many sidebars as you want. */ const sidebars: SidebarsConfig = { // By default, Docusaurus generates a sidebar from the docs folder structure tutorialSidebar: [{ type: "autogenerated", dirName: "." }], // But you can create a sidebar manually /* tutorialSidebar: [ 'intro', 'hello', { type: 'category', label: 'Tutorial', items: ['tutorial-basics/create-a-document'], }, ], */ }; export default sidebars; ================================================ FILE: docs/src/components/HomepageFeatures/index.tsx ================================================ import Heading from "@theme/Heading"; import clsx from "clsx"; import styles from "./styles.module.css"; type FeatureItem = { title: string; Svg?: React.ComponentType>; imageUrl?: string; imageAlt?: string; description: JSX.Element; }; const FeatureList: FeatureItem[] = [ { title: "Easy Configuration", Svg: require("@site/static/img/undraw_docusaurus_mountain.svg").default, description: <>Configure your entire media stack with a single YAML file. Simple, intuitive, and powerful configuration options., }, { title: "Multi-Platform Support", Svg: require("@site/static/img/undraw_docusaurus_tree.svg").default, description: ( <> Run Configarr anywhere with our Docker container or deploy it on Kubernetes. Perfect for both home servers and cloud environments. ), }, { title: "Automated Setup", Svg: require("@site/static/img/undraw_docusaurus_react.svg").default, description: ( <> Let Configarr handle the complex setup of your media applications. From Sonarr,Radarr,Lidarr,Readarr, Whisparr: we've got you covered! ), }, { title: "TRaSH-Guides Support", imageUrl: require("@site/static/img/trash_logo.webp").default, //"https://trash-guides.info/img/logo.png" , imageAlt: "Logo of TRaSH-Guides", description: ( <> Seamlessly integrate TRaSH-Guides into your workflow with robust support for its comprehensive documentation and automation tools. Effortlessly configure QualityProfiles, CustomFormats, and other advanced settings to optimize your media management experience, ensuring precise and efficient handling of your library. ), }, { title: "Experimental support", Svg: require("@site/static/img/experiment.svg").default, description: ( <> Explore cutting-edge features with experimental support for popular Arr tools like Readarr, Lidarr, and Whisparr. Stay ahead of the curve by testing innovative functionalities designed to enhance your media automation and management capabilities. ), }, { title: "Community Driven", Svg: require("@site/static/img/undraw_docusaurus_react.svg").default, description: ( <>Written for the community and working with the community to provide the best experience for managing your media stack! ), }, ]; function Feature({ title, Svg, description, imageUrl, imageAlt }: FeatureItem) { return (
{Svg ? ( ) : ( {imageAlt} )}
{title}

{description}

); } export default function HomepageFeatures(): JSX.Element { return (
{FeatureList.map((props, idx) => ( ))}
); } ================================================ FILE: docs/src/components/HomepageFeatures/styles.module.css ================================================ .features { display: flex; align-items: center; padding: 2rem 0; width: 100%; } .featureSvg { height: 200px; width: 200px; } ================================================ FILE: docs/src/css/custom.css ================================================ /** * Any CSS included here will be global. The classic template * bundles Infima by default. Infima is a CSS framework designed to * work well for content-centric websites. */ /* You can override the default Infima variables here. */ :root { --ifm-color-primary: #8659c4; --ifm-color-primary-dark: #603d8c; --ifm-color-primary-darker: #4e3271; --ifm-color-primary-darkest: #331a51; --ifm-color-primary-light: #9d77d5; --ifm-color-primary-lighter: #b99de3; --ifm-color-primary-lightest: #d3c3ef; --ifm-code-font-size: 95%; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); } /* --color-studio-50: #f9f7fd; --color-studio-100: #f2edfa; --color-studio-200: #e6def6; --color-studio-300: #d3c3ef; --color-studio-400: #b99de3; --color-studio-500: #9d77d5; --color-studio-600: #8659c4; --color-studio-700: #7649b2; --color-studio-800: #603d8c; --color-studio-900: #4e3271; --color-studio-950: #331a51; */ /* For readability concerns, you should choose a lighter palette in dark mode. */ [data-theme="dark"] { --ifm-color-primary: #9d77d5; --ifm-color-primary-dark: #8659c4; --ifm-color-primary-darker: #7649b2; --ifm-color-primary-darkest: #603d8c; --ifm-color-primary-light: #b99de3; --ifm-color-primary-lighter: #d3c3ef; --ifm-color-primary-lightest: #e6def6; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); } .configarrHeader { font-size: 18px; font-weight: bolder; } .comparisonTableNote { font-size: 12px; } .youtubeContainer { position: relative; overflow: hidden; width: 100%; padding-top: 56.25%; /* 16:9 Aspect Ratio (divide 9 by 16 = 0.5625) */ } .youtubeVideo { position: absolute; top: 0; left: 0; bottom: 0; right: 0; width: 100%; height: 100%; } .navbarGithubStars { height: 20px; /* var(--docusaurus-announcement-bar-height); */ width: 90px; } .configarr-badge { background-color: var(--ifm-color-primary); border-color: var(--ifm-color-primary); font-size: 50%; } .table-of-contents .configarr-badge { font-size: 75%; padding: 2px 4px; } ================================================ FILE: docs/src/pages/index.module.css ================================================ /** * CSS files with the .module.css suffix will be treated as CSS modules * and scoped locally. */ .heroBanner { padding: 4rem 0; text-align: center; position: relative; overflow: hidden; } @media screen and (max-width: 996px) { .heroBanner { padding: 2rem; } } .buttons { display: flex; align-items: center; justify-content: center; gap: 2rem; } .buttonsGithubStars { display: flex; } ================================================ FILE: docs/src/pages/index.tsx ================================================ import Link from "@docusaurus/Link"; import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; import HomepageFeatures from "@site/src/components/HomepageFeatures"; import Heading from "@theme/Heading"; import Layout from "@theme/Layout"; import clsx from "clsx"; import Head from "@docusaurus/Head"; import styles from "./index.module.css"; import useBaseUrl from "@docusaurus/useBaseUrl"; function HomepageHeader() { const { siteConfig } = useDocusaurusContext(); return (
Configarr Logo {siteConfig.title}

{siteConfig.tagline}

Get Started !