Full Code of raydak-labs/configarr for AI

main bf579b515124 cached
236 files
2.4 MB
647.1k tokens
1339 symbols
1 requests
Download .txt
Showing preview only (2,587K chars total). Download the full file or copy to clipboard to get everything.
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
        "<node_internals>/**",

        // 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. <https://fsf.org/>
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.

<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year>  <name of author>

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 <https://www.gnu.org/licenses/>.

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
<https://www.gnu.org/licenses/>.


================================================
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)

<p align="center" >
  <img width="150"  src="./docs/static/img/logo.webp" alt="Logo of configarr" />
</p>

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.*)(?<!\\bWEB[-_. ])\\bDL\\b|\\[DE\\+[a-z]{2}\\]|\\[[a-z]{2}\\+DE\\]|ger,\\s*[a-z]{3}\\]|\\[[a-z]{3}\\s*,\\s*ger\\]"
      }
    },
    {
      "name": "German",
      "implementation": "LanguageSpecification",
      "negate": false,
      "required": true,
      "fields": {
        "value": 4
      }
    },
    {
      "name": "English",
      "implementation": "LanguageSpecification",
      "negate": false,
      "required": true,
      "fields": {
        "value": 1
      }
    }
  ]
}


================================================
FILE: custom/cfs/lang-de-dl.json
================================================
{
  "trash_id": "lang-de-dl-version1",
  "trash_scores": {},
  "name": "German DL",
  "includeCustomFormatWhenRenaming": true,
  "specifications": [
    {
      "name": "German DL",
      "implementation": "ReleaseTitleSpecification",
      "negate": false,
      "required": true,
      "fields": {
        "value": "(?i)german\\s*\\.?dl|(?<=\\bGerman\\b.*)(?<!\\bWEB[-_. ])\\bDL\\b|\\[DE\\+[a-z]{2}\\]|\\[[a-z]{2}\\+DE\\]|ger,\\s*[a-z]{3}\\]|\\[[a-z]{3}\\s*,\\s*ger\\]"
      }
    }
  ]
}


================================================
FILE: custom/cfs/lang-de-only.json
================================================
{
  "trash_id": "lang-de-only-version1",
  "trash_scores": {},
  "name": "Language: German Only",
  "includeCustomFormatWhenRenaming": false,
  "specifications": [
    {
      "name": "Language GER",
      "implementation": "LanguageSpecification",
      "negate": false,
      "required": true,
      "fields": {
        "value": 4
      }
    },
    {
      "name": "NOT German DL",
      "implementation": "ReleaseTitleSpecification",
      "negate": true,
      "required": true,
      "fields": {
        "value": "(?i)german\\s*\\.?dl|(?<=\\bGerman\\b.*)(?<!\\bWEB[-_. ])\\bDL\\b|\\[DE\\+[a-z]{2}\\]|\\[[a-z]{2}\\+DE\\]|ger,\\s*[a-z]{3}\\]|\\[[a-z]{3}\\s*,\\s*ger\\]"
      }
    },
    {
      "name": "Not English",
      "implementation": "LanguageSpecification",
      "negate": true,
      "required": true,
      "fields": {
        "value": 1
      }
    }
  ]
}


================================================
FILE: custom/cfs/lang-en-only.json
================================================
{
  "trash_id": "lang-en-only-version1",
  "trash_scores": {},
  "name": " Language: English Only",
  "includeCustomFormatWhenRenaming": false,
  "specifications": [
    {
      "name": "Language ENG",
      "implementation": "LanguageSpecification",
      "negate": false,
      "required": true,
      "fields": {
        "value": 1
      }
    },
    {
      "name": "NOT German DL",
      "implementation": "ReleaseTitleSpecification",
      "negate": true,
      "required": true,
      "fields": {
        "value": "(?i)german\\s*\\.?dl|(?<=\\bGerman\\b.*)(?<!\\bWEB[-_. ])\\bDL\\b|\\[DE\\+[a-z]{2}\\]|\\[[a-z]{2}\\+DE\\]|ger,\\s*[a-z]{3}\\]|\\[[a-z]{3}\\s*,\\s*ger\\]"
      }
    },
    {
      "name": "NOT German Language",
      "implementation": "LanguageSpecification",
      "negate": true,
      "required": true,
      "fields": {
        "value": 4
      }
    }
  ]
}


================================================
FILE: custom/cfs/lang-mic-dub.json
================================================
{
  "trash_id": "lang-mic-dub-version1",
  "trash_scores": {},
  "name": "MIC DUB",
  "includeCustomFormatWhenRenaming": true,
  "specifications": [
    {
      "name": "MD",
      "implementation": "ReleaseTitleSpecification",
      "negate": false,
      "required": true,
      "fields": {
        "value": "((19|20|21)[0-9]{2}).*?(?<=^|[ .-])MD(?=[ .-]|$).*?(?<=^|[ .-])GERMAN(?=[ .-]|$)|((19|20|21)[0-9]{2}).*?(?<=^|[ .-])GERMAN(?=[ .-]|$).*?(?<=^|[ .-])MD(?=[ .-]|$)"
      }
    }
  ]
}


================================================
FILE: custom/cfs/lang-not-en-de.json
================================================
{
  "trash_id": "lang-not-en-de-version1",
  "trash_scores": {},
  "name": "Language: Not ENG/GER",
  "includeCustomFormatWhenRenaming": false,
  "specifications": [
    {
      "name": "Not English Language",
      "implementation": "LanguageSpecification",
      "negate": true,
      "required": true,
      "fields": {
        "value": 1
      }
    },
    {
      "name": "Not German Language",
      "implementation": "LanguageSpecification",
      "negate": true,
      "required": true,
      "fields": {
        "value": 4
      }
    },
    {
      "name": "Not German in Title",
      "implementation": "ReleaseTitleSpecification",
      "negate": true,
      "required": true,
      "fields": {
        "value": "(?i)\\bgerman\\b"
      }
    }
  ]
}


================================================
FILE: docs/.gitignore
================================================
# Dependencies
/node_modules

# Production
/build

# Generated files
.docusaurus
.cache-loader

# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*


================================================
FILE: docs/README.md
================================================
# Configarr documentation

This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.

### Installation

```
$ pnpm
```

### Local Development

```
$ pnpm start
```

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

### Build

```
$ pnpm build
```

This command generates static content into the `build` directory and can be served using any static contents hosting service.

### Deployment

Using SSH:

```
$ USE_SSH=true pnpm deploy
```

Not using SSH:

```
$ GIT_USER=<Your GitHub username> 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";

#

<CHANGELOG components={props.components} />


================================================
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                         | <div class="configarrHeader">Configarr</div> |     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:              |                    |                    |

<div className="comparisonTableNote">
  \*1: You start with one of the provided templates and can adjust things. But not just start with a clean QualityProfile.
</div>

## Sonarr

| Features                         | <div class="configarrHeader">Configarr</div> |     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:              |                    |                    |

<div className="comparisonTableNote">
  \*1: You start with one of the provided templates and can adjust things. But not just start with a clean QualityProfile.
</div>

## Whisparr

| Features                       | <div class="configarrHeader">Configarr</div> | 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                       | <div class="configarrHeader">Configarr</div> | 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                       | <div class="configarrHeader">Configarr</div> | 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** <span className="theme-doc-version-badge badge badge--secondary configarr-badge">1.18.0</span> <span className="badge badge--warning">Experimental</span>: 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.

<details>
  <summary>Config.yml</summary>
  <CodeBlock language="yml" title="config.yml">{ConfigFileSample}</CodeBlock>
</details>

### 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** <span className="theme-doc-version-badge badge badge--secondary configarr-badge">1.21.0</span>

`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 <span className="theme-doc-version-badge badge badge--secondary configarr-badge">1.16.0</span> {#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 <span className="theme-doc-version-badge badge badge--secondary configarr-badge">1.26.0</span> {#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 <span className="theme-doc-version-badge badge badge--secondary configarr-badge">1.27.0</span> {#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 <span className="theme-doc-version-badge badge badge--secondary configarr-badge">1.23.0</span> {#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.

  <details>
    <summary>CustomFormats with unmanaged QualityProfiles</summary>
    <CodeBlock language="yml" title="CustomFormats with unmanaged QualityProfiles">{ExampleUnamanagedCustomFormats}</CodeBlock>
  </details>

- <span className="theme-doc-version-badge badge badge--secondary configarr-badge">1.16.0</span> 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 <span className="theme-doc-version-badge badge badge--secondary configarr-badge">1.19.0</span>

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 <span className="theme-doc-version-badge badge badge--secondary configarr-badge">1.19.0</span>

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 <span className="theme-doc-version-badge badge badge--secondary configarr-badge">1.20.0</span>

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 add
Download .txt
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
Download .txt
SYMBOL INDEX (1339 symbols across 89 files)

FILE: docs/docusaurus.config.ts
  method injectHtmlTags (line 72) | injectHtmlTags() {

FILE: docs/src/components/HomepageFeatures/index.tsx
  type FeatureItem (line 5) | type FeatureItem = {
  function Feature (line 69) | function Feature({ title, Svg, description, imageUrl, imageAlt }: Featur...
  function HomepageFeatures (line 87) | function HomepageFeatures(): JSX.Element {

FILE: docs/src/pages/index.tsx
  function HomepageHeader (line 12) | function HomepageHeader() {
  function Home (line 41) | function Home(): JSX.Element {

FILE: generate-api.ts
  constant PATH_TO_OUTPUT_DIR (line 5) | const PATH_TO_OUTPUT_DIR = path.resolve(process.cwd(), "./src/__generate...
  constant PATH_SONARR_DIR (line 6) | const PATH_SONARR_DIR = path.resolve(PATH_TO_OUTPUT_DIR, "sonarr");
  constant PATH_RADARR_DIR (line 7) | const PATH_RADARR_DIR = path.resolve(PATH_TO_OUTPUT_DIR, "radarr");
  constant PATH_WHISPARR_DIR (line 8) | const PATH_WHISPARR_DIR = path.resolve(PATH_TO_OUTPUT_DIR, "whisparr");
  constant PATH_READARR_DIR (line 9) | const PATH_READARR_DIR = path.resolve(PATH_TO_OUTPUT_DIR, "readarr");
  constant PATH_LIDARR_DIR (line 10) | const PATH_LIDARR_DIR = path.resolve(PATH_TO_OUTPUT_DIR, "lidarr");

FILE: src/__generated__/lidarr/Api.ts
  class Api (line 85) | class Api<SecurityDataType = unknown> {
    method constructor (line 88) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/lidarr/Content.ts
  class Content (line 15) | class Content<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/lidarr/Feed.ts
  class Feed (line 15) | class Feed<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/lidarr/Login.ts
  class Login (line 15) | class Login<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/lidarr/Logout.ts
  class Logout (line 15) | class Logout<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/lidarr/Path.ts
  class Path (line 15) | class Path<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/lidarr/Ping.ts
  class Ping (line 16) | class Ping<SecurityDataType = unknown> {
    method constructor (line 19) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/lidarr/data-contracts.ts
  type WriteAudioTagsType (line 13) | enum WriteAudioTagsType {
  type UpdateMechanism (line 20) | enum UpdateMechanism {
  type TrackedDownloadStatus (line 28) | enum TrackedDownloadStatus {
  type TrackedDownloadState (line 34) | enum TrackedDownloadState {
  type SortDirection (line 46) | enum SortDirection {
  type RuntimeMode (line 52) | enum RuntimeMode {
  type RescanAfterRefreshType (line 58) | enum RescanAfterRefreshType {
  type RejectionType (line 64) | enum RejectionType {
  type ProxyType (line 69) | enum ProxyType {
  type ProviderMessageType (line 75) | enum ProviderMessageType {
  type ProperDownloadTypes (line 81) | enum ProperDownloadTypes {
  type PrivacyLevel (line 87) | enum PrivacyLevel {
  type NewItemMonitorTypes (line 94) | enum NewItemMonitorTypes {
  type MonitorTypes (line 100) | enum MonitorTypes {
  type MediaCoverTypes (line 111) | enum MediaCoverTypes {
  type ImportListType (line 124) | enum ImportListType {
  type ImportListMonitorType (line 132) | enum ImportListMonitorType {
  type HealthCheckResult (line 138) | enum HealthCheckResult {
  type FileDateType (line 145) | enum FileDateType {
  type EntityHistoryEventType (line 150) | enum EntityHistoryEventType {
  type DownloadProtocol (line 164) | enum DownloadProtocol {
  type DatabaseType (line 170) | enum DatabaseType {
  type CommandTrigger (line 175) | enum CommandTrigger {
  type CommandStatus (line 181) | enum CommandStatus {
  type CommandResult (line 191) | enum CommandResult {
  type CommandPriority (line 197) | enum CommandPriority {
  type CertificateValidationType (line 203) | enum CertificateValidationType {
  type BackupType (line 209) | enum BackupType {
  type AuthenticationType (line 215) | enum AuthenticationType {
  type AuthenticationRequiredType (line 222) | enum AuthenticationRequiredType {
  type ArtistStatusType (line 227) | enum ArtistStatusType {
  type ApplyTags (line 233) | enum ApplyTags {
  type AllowFingerprinting (line 239) | enum AllowFingerprinting {
  type AlbumAddType (line 245) | enum AlbumAddType {
  type AddAlbumOptions (line 250) | interface AddAlbumOptions {
  type AddArtistOptions (line 255) | interface AddArtistOptions {
  type AlbumReleaseResource (line 262) | interface AlbumReleaseResource {
  type AlbumResource (line 284) | interface AlbumResource {
  type AlbumResourcePagingResource (line 319) | interface AlbumResourcePagingResource {
  type AlbumStatisticsResource (line 331) | interface AlbumStatisticsResource {
  type AlbumStudioArtistResource (line 344) | interface AlbumStudioArtistResource {
  type AlbumStudioResource (line 351) | interface AlbumStudioResource {
  type AlbumsMonitoredResource (line 357) | interface AlbumsMonitoredResource {
  type ArtistEditorResource (line 362) | interface ArtistEditorResource {
  type ArtistResource (line 378) | interface ArtistResource {
  type ArtistStatisticsResource (line 421) | interface ArtistStatisticsResource {
  type ArtistTitleInfo (line 436) | interface ArtistTitleInfo {
  type AutoTaggingResource (line 443) | interface AutoTaggingResource {
  type AutoTaggingSpecificationSchema (line 453) | interface AutoTaggingSpecificationSchema {
  type BackupResource (line 464) | interface BackupResource {
  type BlocklistBulkResource (line 476) | interface BlocklistBulkResource {
  type BlocklistResource (line 480) | interface BlocklistResource {
  type BlocklistResourcePagingResource (line 497) | interface BlocklistResourcePagingResource {
  type Command (line 509) | interface Command {
  type CommandResource (line 527) | interface CommandResource {
  type CustomFilterResource (line 556) | interface CustomFilterResource {
  type CustomFormatBulkResource (line 564) | interface CustomFormatBulkResource {
  type CustomFormatResource (line 570) | interface CustomFormatResource {
  type CustomFormatSpecificationSchema (line 578) | interface CustomFormatSpecificationSchema {
  type DelayProfileResource (line 591) | interface DelayProfileResource {
  type DiskSpaceResource (line 611) | interface DiskSpaceResource {
  type DownloadClientBulkResource (line 622) | interface DownloadClientBulkResource {
  type DownloadClientConfigResource (line 633) | interface DownloadClientConfigResource {
  type DownloadClientResource (line 642) | interface DownloadClientResource {
  type Field (line 663) | interface Field {
  type HealthResource (line 684) | interface HealthResource {
  type HistoryResource (line 693) | interface HistoryResource {
  type HistoryResourcePagingResource (line 718) | interface HistoryResourcePagingResource {
  type HostConfigResource (line 730) | interface HostConfigResource {
  type ImportListBulkResource (line 778) | interface ImportListBulkResource {
  type ImportListExclusionResource (line 788) | interface ImportListExclusionResource {
  type ImportListResource (line 795) | interface ImportListResource {
  type IndexerBulkResource (line 825) | interface IndexerBulkResource {
  type IndexerConfigResource (line 836) | interface IndexerConfigResource {
  type IndexerFlagResource (line 849) | interface IndexerFlagResource {
  type IndexerResource (line 856) | interface IndexerResource {
  type IsoCountry (line 881) | interface IsoCountry {
  type LanguageResource (line 886) | interface LanguageResource {
  type Links (line 893) | interface Links {
  type LocalizationResource (line 898) | interface LocalizationResource {
  type LogFileResource (line 904) | interface LogFileResource {
  type LogResource (line 914) | interface LogResource {
  type LogResourcePagingResource (line 927) | interface LogResourcePagingResource {
  type ManualImportResource (line 939) | interface ManualImportResource {
  type ManualImportUpdateResource (line 965) | interface ManualImportUpdateResource {
  type MediaCover (line 989) | interface MediaCover {
  type MediaInfoModel (line 996) | interface MediaInfoModel {
  type MediaInfoResource (line 1008) | interface MediaInfoResource {
  type MediaManagementConfigResource (line 1019) | interface MediaManagementConfigResource {
  type MediumResource (line 1047) | interface MediumResource {
  type Member (line 1054) | interface Member {
  type MetadataProfileResource (line 1060) | interface MetadataProfileResource {
  type MetadataProviderConfigResource (line 1069) | interface MetadataProviderConfigResource {
  type MetadataResource (line 1078) | interface MetadataResource {
  type MonitoringOptions (line 1094) | interface MonitoringOptions {
  type NamingConfigResource (line 1100) | interface NamingConfigResource {
  type NotificationResource (line 1118) | interface NotificationResource {
  type ParseResource (line 1162) | interface ParseResource {
  type ParsedAlbumInfo (line 1174) | interface ParsedAlbumInfo {
  type ParsedTrackInfo (line 1192) | interface ParsedTrackInfo {
  type PingResource (line 1222) | interface PingResource {
  type PrimaryAlbumType (line 1226) | interface PrimaryAlbumType {
  type ProfileFormatItemResource (line 1232) | interface ProfileFormatItemResource {
  type ProfilePrimaryAlbumTypeItemResource (line 1242) | interface ProfilePrimaryAlbumTypeItemResource {
  type ProfileReleaseStatusItemResource (line 1249) | interface ProfileReleaseStatusItemResource {
  type ProfileSecondaryAlbumTypeItemResource (line 1256) | interface ProfileSecondaryAlbumTypeItemResource {
  type ProviderMessage (line 1263) | interface ProviderMessage {
  type Quality (line 1268) | interface Quality {
  type QualityDefinitionResource (line 1274) | interface QualityDefinitionResource {
  type QualityModel (line 1289) | interface QualityModel {
  type QualityProfileQualityItemResource (line 1294) | interface QualityProfileQualityItemResource {
  type QualityProfileResource (line 1303) | interface QualityProfileResource {
  type QueueBulkResource (line 1318) | interface QueueBulkResource {
  type QueueResource (line 1322) | interface QueueResource {
  type QueueResourcePagingResource (line 1364) | interface QueueResourcePagingResource {
  type QueueStatusResource (line 1376) | interface QueueStatusResource {
  type Ratings (line 1391) | interface Ratings {
  type Rejection (line 1398) | interface Rejection {
  type ReleaseProfileResource (line 1403) | interface ReleaseProfileResource {
  type ReleaseResource (line 1415) | interface ReleaseResource {
  type ReleaseStatus (line 1475) | interface ReleaseStatus {
  type RemotePathMappingResource (line 1481) | interface RemotePathMappingResource {
  type RenameTrackResource (line 1489) | interface RenameTrackResource {
  type RetagTrackResource (line 1503) | interface RetagTrackResource {
  type Revision (line 1517) | interface Revision {
  type RootFolderResource (line 1525) | interface RootFolderResource {
  type SearchResource (line 1545) | interface SearchResource {
  type SecondaryAlbumType (line 1553) | interface SecondaryAlbumType {
  type SelectOption (line 1559) | interface SelectOption {
  type SystemResource (line 1568) | interface SystemResource {
  type TagDetailsResource (line 1605) | interface TagDetailsResource {
  type TagDifference (line 1619) | interface TagDifference {
  type TagResource (line 1625) | interface TagResource {
  type TaskResource (line 1631) | interface TaskResource {
  type TrackFileListResource (line 1648) | interface TrackFileListResource {
  type TrackFileResource (line 1655) | interface TrackFileResource {
  type TrackResource (line 1682) | interface TrackResource {
  type TrackedDownloadStatusMessage (line 1708) | interface TrackedDownloadStatusMessage {
  type UiConfigResource (line 1713) | interface UiConfigResource {
  type UpdateChanges (line 1734) | interface UpdateChanges {
  type UpdateResource (line 1739) | interface UpdateResource {

FILE: src/__generated__/radarr/Api.ts
  class Api (line 91) | class Api<SecurityDataType = unknown> {
    method constructor (line 94) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/radarr/Content.ts
  class Content (line 15) | class Content<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/radarr/Feed.ts
  class Feed (line 16) | class Feed<SecurityDataType = unknown> {
    method constructor (line 19) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/radarr/Login.ts
  class Login (line 15) | class Login<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/radarr/Logout.ts
  class Logout (line 15) | class Logout<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/radarr/Path.ts
  class Path (line 15) | class Path<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/radarr/Ping.ts
  class Ping (line 16) | class Ping<SecurityDataType = unknown> {
    method constructor (line 19) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/radarr/data-contracts.ts
  type UpdateMechanism (line 13) | enum UpdateMechanism {
  type TrackedDownloadStatus (line 21) | enum TrackedDownloadStatus {
  type TrackedDownloadState (line 27) | enum TrackedDownloadState {
  type TMDbCountryCode (line 38) | enum TMDbCountryCode {
  type SourceType (line 54) | enum SourceType {
  type SortDirection (line 61) | enum SortDirection {
  type RuntimeMode (line 67) | enum RuntimeMode {
  type RescanAfterRefreshType (line 73) | enum RescanAfterRefreshType {
  type RejectionType (line 79) | enum RejectionType {
  type RatingType (line 84) | enum RatingType {
  type QueueStatus (line 89) | enum QueueStatus {
  type QualitySource (line 102) | enum QualitySource {
  type ProxyType (line 115) | enum ProxyType {
  type ProviderMessageType (line 121) | enum ProviderMessageType {
  type ProperDownloadTypes (line 127) | enum ProperDownloadTypes {
  type PrivacyLevel (line 133) | enum PrivacyLevel {
  type MovieStatusType (line 140) | enum MovieStatusType {
  type MovieRuntimeFormatType (line 148) | enum MovieRuntimeFormatType {
  type MovieHistoryEventType (line 153) | enum MovieHistoryEventType {
  type MonitorTypes (line 164) | enum MonitorTypes {
  type Modifier (line 170) | enum Modifier {
  type MediaCoverTypes (line 179) | enum MediaCoverTypes {
  type ImportListType (line 189) | enum ImportListType {
  type HealthCheckResult (line 199) | enum HealthCheckResult {
  type FileDateType (line 206) | enum FileDateType {
  type ExtraFileType (line 212) | enum ExtraFileType {
  type DownloadProtocol (line 218) | enum DownloadProtocol {
  type DatabaseType (line 224) | enum DatabaseType {
  type CreditType (line 229) | enum CreditType {
  type CommandTrigger (line 234) | enum CommandTrigger {
  type CommandStatus (line 240) | enum CommandStatus {
  type CommandResult (line 250) | enum CommandResult {
  type CommandPriority (line 256) | enum CommandPriority {
  type ColonReplacementFormat (line 262) | enum ColonReplacementFormat {
  type CertificateValidationType (line 270) | enum CertificateValidationType {
  type CalendarReleaseType (line 276) | enum CalendarReleaseType {
  type BackupType (line 282) | enum BackupType {
  type AuthenticationType (line 288) | enum AuthenticationType {
  type AuthenticationRequiredType (line 295) | enum AuthenticationRequiredType {
  type ApplyTags (line 300) | enum ApplyTags {
  type AddMovieMethod (line 306) | enum AddMovieMethod {
  type AddMovieOptions (line 312) | interface AddMovieOptions {
  type AlternativeTitleResource (line 320) | interface AlternativeTitleResource {
  type ApiInfoResource (line 330) | interface ApiInfoResource {
  type AutoTaggingResource (line 335) | interface AutoTaggingResource {
  type AutoTaggingSpecificationSchema (line 345) | interface AutoTaggingSpecificationSchema {
  type BackupResource (line 356) | interface BackupResource {
  type BlocklistBulkResource (line 368) | interface BlocklistBulkResource {
  type BlocklistResource (line 372) | interface BlocklistResource {
  type BlocklistResourcePagingResource (line 389) | interface BlocklistResourcePagingResource {
  type CollectionMovieResource (line 401) | interface CollectionMovieResource {
  type CollectionResource (line 422) | interface CollectionResource {
  type CollectionUpdateResource (line 444) | interface CollectionUpdateResource {
  type Command (line 455) | interface Command {
  type CommandResource (line 473) | interface CommandResource {
  type CreditResource (line 502) | interface CreditResource {
  type CustomFilterResource (line 520) | interface CustomFilterResource {
  type CustomFormatBulkResource (line 528) | interface CustomFormatBulkResource {
  type CustomFormatResource (line 534) | interface CustomFormatResource {
  type CustomFormatSpecificationSchema (line 542) | interface CustomFormatSpecificationSchema {
  type DelayProfileResource (line 555) | interface DelayProfileResource {
  type DiskSpaceResource (line 575) | interface DiskSpaceResource {
  type DownloadClientBulkResource (line 586) | interface DownloadClientBulkResource {
  type DownloadClientConfigResource (line 597) | interface DownloadClientConfigResource {
  type DownloadClientResource (line 608) | interface DownloadClientResource {
  type ExtraFileResource (line 629) | interface ExtraFileResource {
  type Field (line 643) | interface Field {
  type HealthResource (line 664) | interface HealthResource {
  type HistoryResource (line 673) | interface HistoryResource {
  type HistoryResourcePagingResource (line 693) | interface HistoryResourcePagingResource {
  type HostConfigResource (line 705) | interface HostConfigResource {
  type ImportListBulkResource (line 753) | interface ImportListBulkResource {
  type ImportListConfigResource (line 765) | interface ImportListConfigResource {
  type ImportListExclusionBulkResource (line 771) | interface ImportListExclusionBulkResource {
  type ImportListExclusionResource (line 776) | interface ImportListExclusionResource {
  type ImportListExclusionResourcePagingResource (line 796) | interface ImportListExclusionResourcePagingResource {
  type ImportListResource (line 808) | interface ImportListResource {
  type ImportRejectionResource (line 836) | interface ImportRejectionResource {
  type IndexerBulkResource (line 841) | interface IndexerBulkResource {
  type IndexerConfigResource (line 852) | interface IndexerConfigResource {
  type IndexerFlagResource (line 870) | interface IndexerFlagResource {
  type IndexerResource (line 877) | interface IndexerResource {
  type Language (line 902) | interface Language {
  type LanguageResource (line 908) | interface LanguageResource {
  type LocalizationLanguageResource (line 915) | interface LocalizationLanguageResource {
  type LogFileResource (line 919) | interface LogFileResource {
  type LogResource (line 929) | interface LogResource {
  type LogResourcePagingResource (line 942) | interface LogResourcePagingResource {
  type ManualImportReprocessResource (line 954) | interface ManualImportReprocessResource {
  type ManualImportResource (line 973) | interface ManualImportResource {
  type MediaCover (line 999) | interface MediaCover {
  type MediaInfoResource (line 1005) | interface MediaInfoResource {
  type MediaManagementConfigResource (line 1031) | interface MediaManagementConfigResource {
  type MetadataConfigResource (line 1059) | interface MetadataConfigResource {
  type MetadataResource (line 1065) | interface MetadataResource {
  type MovieCollectionResource (line 1081) | interface MovieCollectionResource {
  type MovieEditorResource (line 1087) | interface MovieEditorResource {
  type MovieFileListResource (line 1101) | interface MovieFileListResource {
  type MovieFileResource (line 1112) | interface MovieFileResource {
  type MovieResource (line 1138) | interface MovieResource {
  type MovieResourcePagingResource (line 1207) | interface MovieResourcePagingResource {
  type MovieStatisticsResource (line 1219) | interface MovieStatisticsResource {
  type NamingConfigResource (line 1227) | interface NamingConfigResource {
  type NotificationResource (line 1237) | interface NotificationResource {
  type ParseResource (line 1279) | interface ParseResource {
  type ParsedMovieInfo (line 1291) | interface ParsedMovieInfo {
  type PingResource (line 1311) | interface PingResource {
  type ProfileFormatItemResource (line 1315) | interface ProfileFormatItemResource {
  type ProviderMessage (line 1325) | interface ProviderMessage {
  type Quality (line 1330) | interface Quality {
  type QualityDefinitionLimitsResource (line 1340) | interface QualityDefinitionLimitsResource {
  type QualityDefinitionResource (line 1347) | interface QualityDefinitionResource {
  type QualityModel (line 1362) | interface QualityModel {
  type QualityProfileQualityItemResource (line 1367) | interface QualityProfileQualityItemResource {
  type QualityProfileResource (line 1376) | interface QualityProfileResource {
  type QueueBulkResource (line 1394) | interface QueueBulkResource {
  type QueueResource (line 1398) | interface QueueResource {
  type QueueResourcePagingResource (line 1439) | interface QueueResourcePagingResource {
  type QueueStatusResource (line 1451) | interface QueueStatusResource {
  type RatingChild (line 1466) | interface RatingChild {
  type Ratings (line 1474) | interface Ratings {
  type ReleaseProfileResource (line 1482) | interface ReleaseProfileResource {
  type ReleaseResource (line 1495) | interface ReleaseResource {
  type RemotePathMappingResource (line 1559) | interface RemotePathMappingResource {
  type RenameMovieResource (line 1567) | interface RenameMovieResource {
  type Revision (line 1578) | interface Revision {
  type RootFolderResource (line 1586) | interface RootFolderResource {
  type SelectOption (line 1596) | interface SelectOption {
  type SystemResource (line 1606) | interface SystemResource {
  type TagDetailsResource (line 1643) | interface TagDetailsResource {
  type TagResource (line 1657) | interface TagResource {
  type TaskResource (line 1663) | interface TaskResource {
  type TrackedDownloadStatusMessage (line 1680) | interface TrackedDownloadStatusMessage {
  type UiConfigResource (line 1685) | interface UiConfigResource {
  type UnmappedFolder (line 1704) | interface UnmappedFolder {
  type UpdateChanges (line 1710) | interface UpdateChanges {
  type UpdateResource (line 1715) | interface UpdateResource {

FILE: src/__generated__/readarr/Api.ts
  class Api (line 84) | class Api<SecurityDataType = unknown> {
    method constructor (line 87) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/readarr/Content.ts
  class Content (line 15) | class Content<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/readarr/Feed.ts
  class Feed (line 15) | class Feed<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/readarr/Login.ts
  class Login (line 15) | class Login<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/readarr/Logout.ts
  class Logout (line 15) | class Logout<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/readarr/Path.ts
  class Path (line 15) | class Path<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/readarr/Ping.ts
  class Ping (line 16) | class Ping<SecurityDataType = unknown> {
    method constructor (line 19) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/readarr/data-contracts.ts
  type WriteBookTagsType (line 13) | enum WriteBookTagsType {
  type WriteAudioTagsType (line 19) | enum WriteAudioTagsType {
  type UpdateMechanism (line 26) | enum UpdateMechanism {
  type TrackedDownloadStatus (line 34) | enum TrackedDownloadStatus {
  type TrackedDownloadState (line 40) | enum TrackedDownloadState {
  type SortDirection (line 51) | enum SortDirection {
  type RuntimeMode (line 57) | enum RuntimeMode {
  type RescanAfterRefreshType (line 63) | enum RescanAfterRefreshType {
  type RejectionType (line 69) | enum RejectionType {
  type ProxyType (line 74) | enum ProxyType {
  type ProviderMessageType (line 80) | enum ProviderMessageType {
  type ProperDownloadTypes (line 86) | enum ProperDownloadTypes {
  type NewItemMonitorTypes (line 92) | enum NewItemMonitorTypes {
  type MonitorTypes (line 98) | enum MonitorTypes {
  type MediaCoverTypes (line 109) | enum MediaCoverTypes {
  type IndexerFlags (line 122) | enum IndexerFlags {
  type ImportListType (line 132) | enum ImportListType {
  type ImportListMonitorType (line 138) | enum ImportListMonitorType {
  type HealthCheckResult (line 144) | enum HealthCheckResult {
  type FileDateType (line 151) | enum FileDateType {
  type EntityHistoryEventType (line 156) | enum EntityHistoryEventType {
  type DownloadProtocol (line 169) | enum DownloadProtocol {
  type DatabaseType (line 175) | enum DatabaseType {
  type CommandTrigger (line 180) | enum CommandTrigger {
  type CommandStatus (line 186) | enum CommandStatus {
  type CommandResult (line 196) | enum CommandResult {
  type CommandPriority (line 202) | enum CommandPriority {
  type CertificateValidationType (line 208) | enum CertificateValidationType {
  type BookAddType (line 214) | enum BookAddType {
  type BackupType (line 219) | enum BackupType {
  type AuthorStatusType (line 225) | enum AuthorStatusType {
  type AuthenticationType (line 230) | enum AuthenticationType {
  type AuthenticationRequiredType (line 237) | enum AuthenticationRequiredType {
  type ApplyTags (line 242) | enum ApplyTags {
  type AllowFingerprinting (line 248) | enum AllowFingerprinting {
  type AddAuthorOptions (line 254) | interface AddAuthorOptions {
  type AddBookOptions (line 261) | interface AddBookOptions {
  type ApiInfoResource (line 266) | interface ApiInfoResource {
  type Author (line 271) | interface Author {
  type AuthorEditorResource (line 301) | interface AuthorEditorResource {
  type AuthorLazyLoaded (line 316) | interface AuthorLazyLoaded {
  type AuthorMetadata (line 321) | interface AuthorMetadata {
  type AuthorMetadataLazyLoaded (line 346) | interface AuthorMetadataLazyLoaded {
  type AuthorResource (line 351) | interface AuthorResource {
  type AuthorStatisticsResource (line 391) | interface AuthorStatisticsResource {
  type AuthorTitleInfo (line 406) | interface AuthorTitleInfo {
  type BackupResource (line 413) | interface BackupResource {
  type BlocklistBulkResource (line 425) | interface BlocklistBulkResource {
  type BlocklistResource (line 429) | interface BlocklistResource {
  type BlocklistResourcePagingResource (line 446) | interface BlocklistResourcePagingResource {
  type Book (line 458) | interface Book {
  type BookEditorResource (line 490) | interface BookEditorResource {
  type BookFile (line 497) | interface BookFile {
  type BookFileListLazyLoaded (line 525) | interface BookFileListLazyLoaded {
  type BookFileListResource (line 530) | interface BookFileListResource {
  type BookFileResource (line 535) | interface BookFileResource {
  type BookLazyLoaded (line 557) | interface BookLazyLoaded {
  type BookListLazyLoaded (line 562) | interface BookListLazyLoaded {
  type BookResource (line 567) | interface BookResource {
  type BookResourcePagingResource (line 601) | interface BookResourcePagingResource {
  type BookStatisticsResource (line 613) | interface BookStatisticsResource {
  type BooksMonitoredResource (line 626) | interface BooksMonitoredResource {
  type BookshelfAuthorResource (line 631) | interface BookshelfAuthorResource {
  type BookshelfResource (line 638) | interface BookshelfResource {
  type Command (line 644) | interface Command {
  type CommandResource (line 662) | interface CommandResource {
  type CustomFilterResource (line 691) | interface CustomFilterResource {
  type CustomFormat (line 699) | interface CustomFormat {
  type CustomFormatResource (line 707) | interface CustomFormatResource {
  type CustomFormatSpecificationSchema (line 715) | interface CustomFormatSpecificationSchema {
  type DelayProfileResource (line 728) | interface DelayProfileResource {
  type DevelopmentConfigResource (line 748) | interface DevelopmentConfigResource {
  type DiskSpaceResource (line 759) | interface DiskSpaceResource {
  type DownloadClientBulkResource (line 770) | interface DownloadClientBulkResource {
  type DownloadClientConfigResource (line 781) | interface DownloadClientConfigResource {
  type DownloadClientResource (line 790) | interface DownloadClientResource {
  type Edition (line 811) | interface Edition {
  type EditionLazyLoaded (line 840) | interface EditionLazyLoaded {
  type EditionListLazyLoaded (line 845) | interface EditionListLazyLoaded {
  type EditionResource (line 850) | interface EditionResource {
  type Field (line 878) | interface Field {
  type HealthResource (line 898) | interface HealthResource {
  type HistoryResource (line 907) | interface HistoryResource {
  type HistoryResourcePagingResource (line 929) | interface HistoryResourcePagingResource {
  type HostConfigResource (line 941) | interface HostConfigResource {
  type ICustomFormatSpecification (line 987) | interface ICustomFormatSpecification {
  type ImportListBulkResource (line 997) | interface ImportListBulkResource {
  type ImportListExclusionResource (line 1009) | interface ImportListExclusionResource {
  type ImportListResource (line 1016) | interface ImportListResource {
  type IndexerBulkResource (line 1046) | interface IndexerBulkResource {
  type IndexerConfigResource (line 1057) | interface IndexerConfigResource {
  type IndexerFlagResource (line 1070) | interface IndexerFlagResource {
  type IndexerResource (line 1077) | interface IndexerResource {
  type IsoCountry (line 1102) | interface IsoCountry {
  type LanguageResource (line 1107) | interface LanguageResource {
  type Links (line 1114) | interface Links {
  type LogFileResource (line 1119) | interface LogFileResource {
  type LogResource (line 1129) | interface LogResource {
  type LogResourcePagingResource (line 1142) | interface LogResourcePagingResource {
  type ManualImportResource (line 1154) | interface ManualImportResource {
  type ManualImportUpdateResource (line 1178) | interface ManualImportUpdateResource {
  type MediaCover (line 1199) | interface MediaCover {
  type MediaInfoModel (line 1206) | interface MediaInfoModel {
  type MediaInfoResource (line 1218) | interface MediaInfoResource {
  type MediaManagementConfigResource (line 1229) | interface MediaManagementConfigResource {
  type MetadataProfile (line 1254) | interface MetadataProfile {
  type MetadataProfileLazyLoaded (line 1270) | interface MetadataProfileLazyLoaded {
  type MetadataProfileResource (line 1275) | interface MetadataProfileResource {
  type MetadataProviderConfigResource (line 1291) | interface MetadataProviderConfigResource {
  type MetadataResource (line 1301) | interface MetadataResource {
  type MonitoringOptions (line 1317) | interface MonitoringOptions {
  type NamingConfigResource (line 1323) | interface NamingConfigResource {
  type NotificationResource (line 1340) | interface NotificationResource {
  type ParseResource (line 1386) | interface ParseResource {
  type ParsedBookInfo (line 1395) | interface ParsedBookInfo {
  type ParsedTrackInfo (line 1412) | interface ParsedTrackInfo {
  type PingResource (line 1450) | interface PingResource {
  type ProfileFormatItem (line 1454) | interface ProfileFormatItem {
  type ProfileFormatItemResource (line 1460) | interface ProfileFormatItemResource {
  type ProviderMessage (line 1470) | interface ProviderMessage {
  type Quality (line 1475) | interface Quality {
  type QualityDefinitionResource (line 1481) | interface QualityDefinitionResource {
  type QualityModel (line 1494) | interface QualityModel {
  type QualityProfile (line 1499) | interface QualityProfile {
  type QualityProfileLazyLoaded (line 1514) | interface QualityProfileLazyLoaded {
  type QualityProfileQualityItem (line 1519) | interface QualityProfileQualityItem {
  type QualityProfileQualityItemResource (line 1528) | interface QualityProfileQualityItemResource {
  type QualityProfileResource (line 1537) | interface QualityProfileResource {
  type QueueBulkResource (line 1552) | interface QueueBulkResource {
  type QueueResource (line 1556) | interface QueueResource {
  type QueueResourcePagingResource (line 1592) | interface QueueResourcePagingResource {
  type QueueStatusResource (line 1604) | interface QueueStatusResource {
  type Ratings (line 1619) | interface Ratings {
  type Rejection (line 1628) | interface Rejection {
  type ReleaseProfileResource (line 1633) | interface ReleaseProfileResource {
  type ReleaseResource (line 1645) | interface ReleaseResource {
  type RemotePathMappingResource (line 1705) | interface RemotePathMappingResource {
  type RenameBookResource (line 1713) | interface RenameBookResource {
  type RetagBookResource (line 1726) | interface RetagBookResource {
  type Revision (line 1740) | interface Revision {
  type RootFolderResource (line 1748) | interface RootFolderResource {
  type SelectOption (line 1779) | interface SelectOption {
  type Series (line 1788) | interface Series {
  type SeriesBookLink (line 1804) | interface SeriesBookLink {
  type SeriesBookLinkListLazyLoaded (line 1819) | interface SeriesBookLinkListLazyLoaded {
  type SeriesBookLinkResource (line 1824) | interface SeriesBookLinkResource {
  type SeriesLazyLoaded (line 1836) | interface SeriesLazyLoaded {
  type SeriesListLazyLoaded (line 1841) | interface SeriesListLazyLoaded {
  type SeriesResource (line 1846) | interface SeriesResource {
  type SystemResource (line 1854) | interface SystemResource {
  type TagDetailsResource (line 1891) | interface TagDetailsResource {
  type TagDifference (line 1904) | interface TagDifference {
  type TagResource (line 1910) | interface TagResource {
  type TaskResource (line 1916) | interface TaskResource {
  type TrackedDownloadStatusMessage (line 1933) | interface TrackedDownloadStatusMessage {
  type UiConfigResource (line 1938) | interface UiConfigResource {
  type UpdateChanges (line 1954) | interface UpdateChanges {
  type UpdateResource (line 1959) | interface UpdateResource {

FILE: src/__generated__/sonarr/Api.ts
  class Api (line 87) | class Api<SecurityDataType = unknown> {
    method constructor (line 90) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/sonarr/Content.ts
  class Content (line 15) | class Content<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/sonarr/Feed.ts
  class Feed (line 15) | class Feed<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/sonarr/Login.ts
  class Login (line 15) | class Login<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/sonarr/Logout.ts
  class Logout (line 15) | class Logout<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/sonarr/Path.ts
  class Path (line 15) | class Path<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/sonarr/Ping.ts
  class Ping (line 16) | class Ping<SecurityDataType = unknown> {
    method constructor (line 19) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/sonarr/data-contracts.ts
  type UpdateMechanism (line 13) | enum UpdateMechanism {
  type TrackedDownloadStatus (line 21) | enum TrackedDownloadStatus {
  type TrackedDownloadState (line 27) | enum TrackedDownloadState {
  type SortDirection (line 38) | enum SortDirection {
  type SeriesTypes (line 44) | enum SeriesTypes {
  type SeriesStatusType (line 50) | enum SeriesStatusType {
  type RuntimeMode (line 57) | enum RuntimeMode {
  type RescanAfterRefreshType (line 63) | enum RescanAfterRefreshType {
  type ReleaseType (line 69) | enum ReleaseType {
  type RejectionType (line 76) | enum RejectionType {
  type QueueStatus (line 81) | enum QueueStatus {
  type QualitySource (line 94) | enum QualitySource {
  type ProxyType (line 105) | enum ProxyType {
  type ProviderMessageType (line 111) | enum ProviderMessageType {
  type ProperDownloadTypes (line 117) | enum ProperDownloadTypes {
  type PrivacyLevel (line 123) | enum PrivacyLevel {
  type NewItemMonitorTypes (line 130) | enum NewItemMonitorTypes {
  type MonitorTypes (line 135) | enum MonitorTypes {
  type MediaCoverTypes (line 152) | enum MediaCoverTypes {
  type ListSyncLevelType (line 162) | enum ListSyncLevelType {
  type ImportListType (line 169) | enum ImportListType {
  type HealthCheckResult (line 178) | enum HealthCheckResult {
  type FileDateType (line 185) | enum FileDateType {
  type EpisodeTitleRequiredType (line 191) | enum EpisodeTitleRequiredType {
  type EpisodeHistoryEventType (line 197) | enum EpisodeHistoryEventType {
  type DownloadProtocol (line 208) | enum DownloadProtocol {
  type DatabaseType (line 214) | enum DatabaseType {
  type CommandTrigger (line 219) | enum CommandTrigger {
  type CommandStatus (line 225) | enum CommandStatus {
  type CommandResult (line 235) | enum CommandResult {
  type CommandPriority (line 241) | enum CommandPriority {
  type CertificateValidationType (line 247) | enum CertificateValidationType {
  type BackupType (line 253) | enum BackupType {
  type AuthenticationType (line 259) | enum AuthenticationType {
  type AuthenticationRequiredType (line 266) | enum AuthenticationRequiredType {
  type ApplyTags (line 271) | enum ApplyTags {
  type AddSeriesOptions (line 277) | interface AddSeriesOptions {
  type AlternateTitleResource (line 285) | interface AlternateTitleResource {
  type AutoTaggingResource (line 295) | interface AutoTaggingResource {
  type AutoTaggingSpecificationSchema (line 305) | interface AutoTaggingSpecificationSchema {
  type BackupResource (line 316) | interface BackupResource {
  type BlocklistBulkResource (line 328) | interface BlocklistBulkResource {
  type BlocklistResource (line 332) | interface BlocklistResource {
  type BlocklistResourcePagingResource (line 350) | interface BlocklistResourcePagingResource {
  type Command (line 362) | interface Command {
  type CommandResource (line 379) | interface CommandResource {
  type CustomFilterResource (line 408) | interface CustomFilterResource {
  type CustomFormatBulkResource (line 416) | interface CustomFormatBulkResource {
  type CustomFormatResource (line 422) | interface CustomFormatResource {
  type CustomFormatSpecificationSchema (line 430) | interface CustomFormatSpecificationSchema {
  type DelayProfileResource (line 443) | interface DelayProfileResource {
  type DiskSpaceResource (line 463) | interface DiskSpaceResource {
  type DownloadClientBulkResource (line 474) | interface DownloadClientBulkResource {
  type DownloadClientConfigResource (line 485) | interface DownloadClientConfigResource {
  type DownloadClientResource (line 494) | interface DownloadClientResource {
  type EpisodeFileListResource (line 515) | interface EpisodeFileListResource {
  type EpisodeFileResource (line 523) | interface EpisodeFileResource {
  type EpisodeResource (line 550) | interface EpisodeResource {
  type EpisodeResourcePagingResource (line 593) | interface EpisodeResourcePagingResource {
  type EpisodesMonitoredResource (line 605) | interface EpisodesMonitoredResource {
  type Field (line 610) | interface Field {
  type HealthResource (line 631) | interface HealthResource {
  type HistoryResource (line 640) | interface HistoryResource {
  type HistoryResourcePagingResource (line 663) | interface HistoryResourcePagingResource {
  type HostConfigResource (line 675) | interface HostConfigResource {
  type HttpUri (line 723) | interface HttpUri {
  type ImportListBulkResource (line 734) | interface ImportListBulkResource {
  type ImportListConfigResource (line 744) | interface ImportListConfigResource {
  type ImportListExclusionBulkResource (line 752) | interface ImportListExclusionBulkResource {
  type ImportListExclusionResource (line 757) | interface ImportListExclusionResource {
  type ImportListExclusionResourcePagingResource (line 765) | interface ImportListExclusionResourcePagingResource {
  type ImportListResource (line 777) | interface ImportListResource {
  type ImportRejectionResource (line 806) | interface ImportRejectionResource {
  type IndexerBulkResource (line 811) | interface IndexerBulkResource {
  type IndexerConfigResource (line 822) | interface IndexerConfigResource {
  type IndexerFlagResource (line 835) | interface IndexerFlagResource {
  type IndexerResource (line 842) | interface IndexerResource {
  type Language (line 869) | interface Language {
  type LanguageProfileItemResource (line 875) | interface LanguageProfileItemResource {
  type LanguageProfileResource (line 882) | interface LanguageProfileResource {
  type LanguageResource (line 891) | interface LanguageResource {
  type LocalizationLanguageResource (line 898) | interface LocalizationLanguageResource {
  type LocalizationResource (line 902) | interface LocalizationResource {
  type LogFileResource (line 908) | interface LogFileResource {
  type LogResource (line 918) | interface LogResource {
  type LogResourcePagingResource (line 931) | interface LogResourcePagingResource {
  type ManualImportReprocessResource (line 943) | interface ManualImportReprocessResource {
  type ManualImportResource (line 966) | interface ManualImportResource {
  type MediaCover (line 996) | interface MediaCover {
  type MediaInfoResource (line 1002) | interface MediaInfoResource {
  type MediaManagementConfigResource (line 1028) | interface MediaManagementConfigResource {
  type MetadataResource (line 1055) | interface MetadataResource {
  type MonitoringOptions (line 1071) | interface MonitoringOptions {
  type NamingConfigResource (line 1077) | interface NamingConfigResource {
  type NotificationResource (line 1095) | interface NotificationResource {
  type ParseResource (line 1139) | interface ParseResource {
  type ParsedEpisodeInfo (line 1152) | interface ParsedEpisodeInfo {
  type PingResource (line 1185) | interface PingResource {
  type ProfileFormatItemResource (line 1189) | interface ProfileFormatItemResource {
  type ProviderMessage (line 1199) | interface ProviderMessage {
  type Quality (line 1204) | interface Quality {
  type QualityDefinitionLimitsResource (line 1213) | interface QualityDefinitionLimitsResource {
  type QualityDefinitionResource (line 1220) | interface QualityDefinitionResource {
  type QualityModel (line 1235) | interface QualityModel {
  type QualityProfileQualityItemResource (line 1240) | interface QualityProfileQualityItemResource {
  type QualityProfileResource (line 1249) | interface QualityProfileResource {
  type QueueBulkResource (line 1266) | interface QueueBulkResource {
  type QueueResource (line 1270) | interface QueueResource {
  type QueueResourcePagingResource (line 1317) | interface QueueResourcePagingResource {
  type QueueStatusResource (line 1329) | interface QueueStatusResource {
  type Ratings (line 1344) | interface Ratings {
  type ReleaseEpisodeResource (line 1351) | interface ReleaseEpisodeResource {
  type ReleaseProfileResource (line 1363) | interface ReleaseProfileResource {
  type ReleaseResource (line 1376) | interface ReleaseResource {
  type RemotePathMappingResource (line 1462) | interface RemotePathMappingResource {
  type RenameEpisodeResource (line 1470) | interface RenameEpisodeResource {
  type Revision (line 1484) | interface Revision {
  type RootFolderResource (line 1492) | interface RootFolderResource {
  type SeasonPassResource (line 1502) | interface SeasonPassResource {
  type SeasonPassSeriesResource (line 1507) | interface SeasonPassSeriesResource {
  type SeasonResource (line 1514) | interface SeasonResource {
  type SeasonStatisticsResource (line 1522) | interface SeasonStatisticsResource {
  type SelectOption (line 1540) | interface SelectOption {
  type SeriesEditorResource (line 1549) | interface SeriesEditorResource {
  type SeriesResource (line 1565) | interface SeriesResource {
  type SeriesStatisticsResource (line 1631) | interface SeriesStatisticsResource {
  type SeriesTitleInfo (line 1647) | interface SeriesTitleInfo {
  type SystemResource (line 1655) | interface SystemResource {
  type TagDetailsResource (line 1693) | interface TagDetailsResource {
  type TagResource (line 1707) | interface TagResource {
  type TaskResource (line 1713) | interface TaskResource {
  type TrackedDownloadStatusMessage (line 1730) | interface TrackedDownloadStatusMessage {
  type UiConfigResource (line 1735) | interface UiConfigResource {
  type UnmappedFolder (line 1751) | interface UnmappedFolder {
  type UpdateChanges (line 1757) | interface UpdateChanges {
  type UpdateResource (line 1762) | interface UpdateResource {

FILE: src/__generated__/whisparr/Api.ts
  class Api (line 81) | class Api<SecurityDataType = unknown> {
    method constructor (line 84) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/whisparr/Content.ts
  class Content (line 15) | class Content<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/whisparr/Feed.ts
  class Feed (line 15) | class Feed<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/whisparr/Login.ts
  class Login (line 15) | class Login<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/whisparr/Logout.ts
  class Logout (line 15) | class Logout<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/whisparr/Path.ts
  class Path (line 15) | class Path<SecurityDataType = unknown> {
    method constructor (line 18) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/whisparr/Ping.ts
  class Ping (line 16) | class Ping<SecurityDataType = unknown> {
    method constructor (line 19) | constructor(http: HttpClient<SecurityDataType>) {

FILE: src/__generated__/whisparr/data-contracts.ts
  type UpdateMechanism (line 13) | enum UpdateMechanism {
  type TrackedDownloadStatus (line 21) | enum TrackedDownloadStatus {
  type TrackedDownloadState (line 27) | enum TrackedDownloadState {
  type SortDirection (line 37) | enum SortDirection {
  type SeriesStatusType (line 43) | enum SeriesStatusType {
  type RuntimeMode (line 50) | enum RuntimeMode {
  type RescanAfterRefreshType (line 56) | enum RescanAfterRefreshType {
  type RejectionType (line 62) | enum RejectionType {
  type QualitySource (line 67) | enum QualitySource {
  type ProxyType (line 79) | enum ProxyType {
  type ProviderMessageType (line 85) | enum ProviderMessageType {
  type ProperDownloadTypes (line 91) | enum ProperDownloadTypes {
  type PrivacyLevel (line 97) | enum PrivacyLevel {
  type MonitorTypes (line 104) | enum MonitorTypes {
  type MediaCoverTypes (line 115) | enum MediaCoverTypes {
  type ListSyncLevelType (line 126) | enum ListSyncLevelType {
  type ImportListType (line 133) | enum ImportListType {
  type ImportListMonitorTypes (line 142) | enum ImportListMonitorTypes {
  type HealthCheckResult (line 148) | enum HealthCheckResult {
  type Gender (line 155) | enum Gender {
  type FileDateType (line 161) | enum FileDateType {
  type EpisodeTitleRequiredType (line 167) | enum EpisodeTitleRequiredType {
  type EpisodeHistoryEventType (line 173) | enum EpisodeHistoryEventType {
  type DownloadProtocol (line 184) | enum DownloadProtocol {
  type DayOfWeek (line 190) | enum DayOfWeek {
  type DatabaseType (line 200) | enum DatabaseType {
  type CommandTrigger (line 205) | enum CommandTrigger {
  type CommandStatus (line 211) | enum CommandStatus {
  type CommandResult (line 221) | enum CommandResult {
  type CommandPriority (line 227) | enum CommandPriority {
  type CertificateValidationType (line 233) | enum CertificateValidationType {
  type BackupType (line 239) | enum BackupType {
  type AuthenticationType (line 245) | enum AuthenticationType {
  type AuthenticationRequiredType (line 252) | enum AuthenticationRequiredType {
  type ApplyTags (line 257) | enum ApplyTags {
  type Actor (line 263) | interface Actor {
  type AddSeriesOptions (line 272) | interface AddSeriesOptions {
  type AutoTaggingResource (line 281) | interface AutoTaggingResource {
  type AutoTaggingSpecificationSchema (line 291) | interface AutoTaggingSpecificationSchema {
  type BackupResource (line 302) | interface BackupResource {
  type BlocklistBulkResource (line 314) | interface BlocklistBulkResource {
  type BlocklistResource (line 318) | interface BlocklistResource {
  type BlocklistResourcePagingResource (line 336) | interface BlocklistResourcePagingResource {
  type Command (line 348) | interface Command {
  type CommandResource (line 365) | interface CommandResource {
  type CustomFilterResource (line 393) | interface CustomFilterResource {
  type CustomFormatResource (line 401) | interface CustomFormatResource {
  type CustomFormatSpecificationSchema (line 409) | interface CustomFormatSpecificationSchema {
  type DateOnly (line 422) | interface DateOnly {
  type DelayProfileResource (line 436) | interface DelayProfileResource {
  type DiskSpaceResource (line 456) | interface DiskSpaceResource {
  type DownloadClientBulkResource (line 467) | interface DownloadClientBulkResource {
  type DownloadClientConfigResource (line 478) | interface DownloadClientConfigResource {
  type DownloadClientResource (line 486) | interface DownloadClientResource {
  type EpisodeFileListResource (line 507) | interface EpisodeFileListResource {
  type EpisodeFileResource (line 515) | interface EpisodeFileResource {
  type EpisodeResource (line 539) | interface EpisodeResource {
  type EpisodeResourcePagingResource (line 573) | interface EpisodeResourcePagingResource {
  type EpisodesMonitoredResource (line 585) | interface EpisodesMonitoredResource {
  type Field (line 590) | interface Field {
  type HealthResource (line 611) | interface HealthResource {
  type HistoryResource (line 620) | interface HistoryResource {
  type HistoryResourcePagingResource (line 643) | interface HistoryResourcePagingResource {
  type HostConfigResource (line 655) | interface HostConfigResource {
  type HttpUri (line 700) | interface HttpUri {
  type ImportListBulkResource (line 711) | interface ImportListBulkResource {
  type ImportListConfigResource (line 721) | interface ImportListConfigResource {
  type ImportListExclusionResource (line 729) | interface ImportListExclusionResource {
  type ImportListResource (line 737) | interface ImportListResource {
  type IndexerBulkResource (line 762) | interface IndexerBulkResource {
  type IndexerConfigResource (line 773) | interface IndexerConfigResource {
  type IndexerResource (line 786) | interface IndexerResource {
  type Language (line 813) | interface Language {
  type LanguageProfileItemResource (line 819) | interface LanguageProfileItemResource {
  type LanguageProfileResource (line 826) | interface LanguageProfileResource {
  type LanguageResource (line 835) | interface LanguageResource {
  type LocalizationLanguageResource (line 842) | interface LocalizationLanguageResource {
  type LocalizationResource (line 846) | interface LocalizationResource {
  type LogFileResource (line 852) | interface LogFileResource {
  type LogResource (line 862) | interface LogResource {
  type LogResourcePagingResource (line 875) | interface LogResourcePagingResource {
  type ManualImportReprocessResource (line 887) | interface ManualImportReprocessResource {
  type ManualImportResource (line 907) | interface ManualImportResource {
  type MediaCover (line 934) | interface MediaCover {
  type MediaInfoResource (line 940) | interface MediaInfoResource {
  type MediaManagementConfigResource (line 966) | interface MediaManagementConfigResource {
  type MetadataResource (line 993) | interface MetadataResource {
  type MonitoringOptions (line 1009) | interface MonitoringOptions {
  type NamingConfigResource (line 1016) | interface NamingConfigResource {
  type NotificationResource (line 1035) | interface NotificationResource {
  type ParseResource (line 1077) | interface ParseResource {
  type ParsedEpisodeInfo (line 1090) | interface ParsedEpisodeInfo {
  type PingResource (line 1105) | interface PingResource {
  type ProfileFormatItemResource (line 1109) | interface ProfileFormatItemResource {
  type ProviderMessage (line 1119) | interface ProviderMessage {
  type Quality (line 1124) | interface Quality {
  type QualityDefinitionLimitsResource (line 1133) | interface QualityDefinitionLimitsResource {
  type QualityDefinitionResource (line 1140) | interface QualityDefinitionResource {
  type QualityModel (line 1155) | interface QualityModel {
  type QualityProfileQualityItemResource (line 1160) | interface QualityProfileQualityItemResource {
  type QualityProfileResource (line 1169) | interface QualityProfileResource {
  type QueueBulkResource (line 1186) | interface QueueBulkResource {
  type QueueResource (line 1190) | interface QueueResource {
  type QueueResourcePagingResource (line 1228) | interface QueueResourcePagingResource {
  type QueueStatusResource (line 1240) | interface QueueStatusResource {
  type Ratings (line 1255) | interface Ratings {
  type Rejection (line 1262) | interface Rejection {
  type ReleaseEpisodeResource (line 1267) | interface ReleaseEpisodeResource {
  type ReleaseProfileResource (line 1279) | interface ReleaseProfileResource {
  type ReleaseResource (line 1292) | interface ReleaseResource {
  type RemotePathMappingResource (line 1359) | interface RemotePathMappingResource {
  type RenameEpisodeResource (line 1367) | interface RenameEpisodeResource {
  type Revision (line 1381) | interface Revision {
  type RootFolderResource (line 1389) | interface RootFolderResource {
  type SeasonPassResource (line 1399) | interface SeasonPassResource {
  type SeasonPassSeriesResource (line 1404) | interface SeasonPassSeriesResource {
  type SeasonResource (line 1411) | interface SeasonResource {
  type SeasonStatisticsResource (line 1419) | interface SeasonStatisticsResource {
  type SelectOption (line 1437) | interface SelectOption {
  type SeriesEditorResource (line 1446) | interface SeriesEditorResource {
  type SeriesResource (line 1459) | interface SeriesResource {
  type SeriesStatisticsResource (line 1506) | interface SeriesStatisticsResource {
  type SeriesTitleInfo (line 1522) | interface SeriesTitleInfo {
  type SystemResource (line 1530) | interface SystemResource {
  type TagDetailsResource (line 1568) | interface TagDetailsResource {
  type TagResource (line 1582) | interface TagResource {
  type TaskResource (line 1588) | interface TaskResource {
  type TimeSpan (line 1604) | interface TimeSpan {
  type TrackedDownloadStatusMessage (line 1629) | interface TrackedDownloadStatusMessage {
  type UiConfigResource (line 1634) | interface UiConfigResource {
  type UnmappedFolder (line 1650) | interface UnmappedFolder {
  type UpdateChanges (line 1656) | interface UpdateChanges {
  type UpdateResource (line 1661) | interface UpdateResource {
  type Version (line 1679) | interface Version {

FILE: src/cache.ts
  class ServerCache (line 11) | class ServerCache {
    method constructor (line 20) | constructor(
    method get (line 32) | public get<T>(key: string): T | null {
    method set (line 36) | public set<T>(key: string, value: T): void {
    method qd (line 40) | public get qd() {
    method qd (line 44) | public set qd(newQd: MergedQualityDefinitionResource[]) {
    method qp (line 53) | public get qp() {
    method qp (line 57) | public set qp(newQp: MergedQualityProfileResource[]) {
    method cf (line 64) | public get cf() {
    method cf (line 68) | public set cf(newCf: MergedCustomFormatResource[]) {
    method languages (line 75) | public get languages() {
    method languages (line 79) | public set languages(newLanguages: ArrClientLanguageResource[]) {
    method tags (line 88) | public get tags() {
    method tags (line 91) | public set tags(newTags: MergedTagResource[]) {
    method getDownloadClientSchema (line 98) | public getDownloadClientSchema(): DownloadClientResource[] | null {
    method setDownloadClientSchema (line 102) | public setDownloadClientSchema(schema: DownloadClientResource[]): void {

FILE: src/clients/lidarr-client.ts
  class LidarrClient (line 17) | class LidarrClient implements IArrClient<QualityProfileResource, Quality...
    method constructor (line 20) | constructor(baseUrl: string, apiKey: string) {
    method initialize (line 24) | private initialize(baseUrl: string, apiKey: string) {
    method getLanguages (line 37) | async getLanguages() {
    method getQualityDefinitions (line 42) | getQualityDefinitions() {
    method updateQualityDefinitions (line 46) | async updateQualityDefinitions(definitions: QualityDefinitionResource[...
    method getQualityProfiles (line 52) | getQualityProfiles() {
    method createQualityProfile (line 56) | createQualityProfile(profile: QualityProfileResource) {
    method updateQualityProfile (line 60) | updateQualityProfile(id: string, profile: QualityProfileResource) {
    method deleteQualityProfile (line 64) | deleteQualityProfile(id: string): Promise<void> {
    method getCustomFormats (line 69) | getCustomFormats() {
    method createCustomFormat (line 73) | createCustomFormat(format: CustomFormatResource) {
    method updateCustomFormat (line 77) | updateCustomFormat(id: string, format: CustomFormatResource) {
    method deleteCustomFormat (line 81) | deleteCustomFormat(id: string) {
    method getMetadataProfiles (line 86) | getMetadataProfiles() {
    method getMetadataProfileSchema (line 90) | getMetadataProfileSchema() {
    method createMetadataProfile (line 94) | createMetadataProfile(profile: MetadataProfileResource) {
    method updateMetadataProfile (line 98) | updateMetadataProfile(id: string, profile: MetadataProfileResource) {
    method deleteMetadataProfile (line 102) | deleteMetadataProfile(id: string) {
    method getNaming (line 106) | async getNaming() {
    method updateNaming (line 110) | async updateNaming(id: string, data: any) {
    method getMediamanagement (line 114) | async getMediamanagement() {
    method updateMediamanagement (line 118) | async updateMediamanagement(id: string, data: any) {
    method getUiConfig (line 122) | async getUiConfig(): Promise<UiConfigResource> {
    method updateUiConfig (line 126) | async updateUiConfig(id: string, data: UiConfigResource): Promise<UiCo...
    method getRootfolders (line 130) | async getRootfolders() {
    method addRootFolder (line 134) | async addRootFolder(data: any) {
    method updateRootFolder (line 138) | async updateRootFolder(id: string, data: any) {
    method deleteRootFolder (line 142) | async deleteRootFolder(id: string) {
    method getDelayProfiles (line 147) | async getDelayProfiles() {
    method createDelayProfile (line 151) | async createDelayProfile(profile: any) {
    method updateDelayProfile (line 155) | async updateDelayProfile(id: string, data: any) {
    method deleteDelayProfile (line 159) | async deleteDelayProfile(id: string) {
    method getTags (line 163) | async getTags() {
    method createTag (line 167) | async createTag(tag: any) {
    method getDownloadClientSchema (line 172) | async getDownloadClientSchema(): Promise<DownloadClientResource[]> {
    method getDownloadClients (line 176) | async getDownloadClients(): Promise<DownloadClientResource[]> {
    method createDownloadClient (line 180) | async createDownloadClient(client: DownloadClientResource): Promise<Do...
    method updateDownloadClient (line 184) | async updateDownloadClient(id: string, client: DownloadClientResource)...
    method deleteDownloadClient (line 188) | async deleteDownloadClient(id: string): Promise<void> {
    method testDownloadClient (line 192) | async testDownloadClient(client: DownloadClientResource): Promise<any> {
    method getDownloadClientConfig (line 197) | async getDownloadClientConfig(): Promise<DownloadClientConfigResource> {
    method updateDownloadClientConfig (line 201) | async updateDownloadClientConfig(id: string, config: DownloadClientCon...
    method getRemotePathMappings (line 206) | async getRemotePathMappings(): Promise<RemotePathMappingResource[]> {
    method createRemotePathMapping (line 210) | async createRemotePathMapping(mapping: RemotePathMappingResource): Pro...
    method updateRemotePathMapping (line 214) | async updateRemotePathMapping(id: string, mapping: RemotePathMappingRe...
    method deleteRemotePathMapping (line 218) | async deleteRemotePathMapping(id: string): Promise<void> {
    method getSystemStatus (line 223) | getSystemStatus() {
    method testConnection (line 227) | async testConnection() {

FILE: src/clients/radarr-client.ts
  class RadarrClient (line 17) | class RadarrClient implements IArrClient<QualityProfileResource, Quality...
    method constructor (line 21) | constructor(baseUrl: string, apiKey: string) {
    method initialize (line 25) | private initialize(baseUrl: string, apiKey: string) {
    method getLanguages (line 38) | async getLanguages() {
    method getQualityDefinitions (line 43) | getQualityDefinitions() {
    method updateQualityDefinitions (line 47) | async updateQualityDefinitions(definitions: QualityDefinitionResource[...
    method getQualityProfiles (line 54) | getQualityProfiles(): Promise<QualityProfileResource[]> {
    method createQualityProfile (line 58) | async createQualityProfile(profile: QualityProfileResource): Promise<Q...
    method updateQualityProfile (line 73) | updateQualityProfile(id: string, profile: QualityProfileResource): Pro...
    method deleteQualityProfile (line 77) | deleteQualityProfile(id: string): Promise<void> {
    method getCustomFormats (line 82) | getCustomFormats() {
    method createCustomFormat (line 86) | createCustomFormat(format: CustomFormatResource) {
    method updateCustomFormat (line 90) | updateCustomFormat(id: string, format: CustomFormatResource) {
    method deleteCustomFormat (line 94) | deleteCustomFormat(id: string) {
    method getNaming (line 98) | async getNaming() {
    method updateNaming (line 102) | async updateNaming(id: string, data: any) {
    method getMediamanagement (line 106) | async getMediamanagement() {
    method updateMediamanagement (line 110) | async updateMediamanagement(id: string, data: any) {
    method getUiConfig (line 114) | async getUiConfig(): Promise<UiConfigResource> {
    method updateUiConfig (line 118) | async updateUiConfig(id: string, data: UiConfigResource): Promise<UiCo...
    method getRootfolders (line 122) | async getRootfolders() {
    method addRootFolder (line 126) | async addRootFolder(data: any) {
    method updateRootFolder (line 130) | async updateRootFolder(id: string, data: any) {
    method deleteRootFolder (line 134) | async deleteRootFolder(id: string) {
    method getDelayProfiles (line 139) | async getDelayProfiles() {
    method createDelayProfile (line 143) | async createDelayProfile(profile: any) {
    method updateDelayProfile (line 147) | async updateDelayProfile(id: string, data: any) {
    method deleteDelayProfile (line 151) | async deleteDelayProfile(id: string) {
    method getTags (line 155) | async getTags() {
    method createTag (line 159) | async createTag(tag: any) {
    method getDownloadClientSchema (line 164) | async getDownloadClientSchema(): Promise<DownloadClientResource[]> {
    method getDownloadClients (line 168) | async getDownloadClients(): Promise<DownloadClientResource[]> {
    method createDownloadClient (line 172) | async createDownloadClient(client: DownloadClientResource): Promise<Do...
    method updateDownloadClient (line 176) | async updateDownloadClient(id: string, client: DownloadClientResource)...
    method deleteDownloadClient (line 180) | async deleteDownloadClient(id: string): Promise<void> {
    method testDownloadClient (line 184) | async testDownloadClient(client: DownloadClientResource): Promise<any> {
    method getDownloadClientConfig (line 189) | async getDownloadClientConfig(): Promise<DownloadClientConfigResource> {
    method updateDownloadClientConfig (line 193) | async updateDownloadClientConfig(id: string, config: DownloadClientCon...
    method getRemotePathMappings (line 198) | async getRemotePathMappings(): Promise<RemotePathMappingResource[]> {
    method createRemotePathMapping (line 202) | async createRemotePathMapping(mapping: RemotePathMappingResource): Pro...
    method updateRemotePathMapping (line 206) | async updateRemotePathMapping(id: string, mapping: RemotePathMappingRe...
    method deleteRemotePathMapping (line 210) | async deleteRemotePathMapping(id: string): Promise<void> {
    method getSystemStatus (line 215) | getSystemStatus() {
    method testConnection (line 219) | async testConnection() {

FILE: src/clients/readarr-client.ts
  class ReadarrClient (line 17) | class ReadarrClient implements IArrClient<
    method constructor (line 25) | constructor(baseUrl: string, apiKey: string) {
    method initialize (line 29) | private initialize(baseUrl: string, apiKey: string) {
    method getLanguages (line 42) | async getLanguages() {
    method getQualityDefinitions (line 47) | getQualityDefinitions() {
    method updateQualityDefinitions (line 51) | async updateQualityDefinitions(definitions: QualityDefinitionResource[...
    method getQualityProfiles (line 57) | getQualityProfiles() {
    method createQualityProfile (line 61) | createQualityProfile(profile: QualityProfileResource) {
    method updateQualityProfile (line 65) | updateQualityProfile(id: string, profile: QualityProfileResource) {
    method deleteQualityProfile (line 69) | deleteQualityProfile(id: string): Promise<void> {
    method getCustomFormats (line 74) | getCustomFormats() {
    method createCustomFormat (line 78) | createCustomFormat(format: CustomFormatResource) {
    method updateCustomFormat (line 82) | updateCustomFormat(id: string, format: CustomFormatResource) {
    method deleteCustomFormat (line 86) | deleteCustomFormat(id: string) {
    method getMetadataProfiles (line 91) | async getMetadataProfiles() {
    method createMetadataProfile (line 95) | async createMetadataProfile(profile: MetadataProfileResource) {
    method updateMetadataProfile (line 99) | async updateMetadataProfile(id: string, profile: MetadataProfileResour...
    method deleteMetadataProfile (line 103) | async deleteMetadataProfile(id: string) {
    method getNaming (line 107) | async getNaming() {
    method updateNaming (line 111) | async updateNaming(id: string, data: any) {
    method getMediamanagement (line 115) | async getMediamanagement() {
    method updateMediamanagement (line 119) | async updateMediamanagement(id: string, data: any) {
    method getUiConfig (line 123) | async getUiConfig(): Promise<UiConfigResource> {
    method updateUiConfig (line 127) | async updateUiConfig(id: string, data: UiConfigResource): Promise<UiCo...
    method getRootfolders (line 131) | async getRootfolders() {
    method addRootFolder (line 135) | async addRootFolder(data: any) {
    method updateRootFolder (line 139) | async updateRootFolder(id: string, data: any) {
    method deleteRootFolder (line 143) | async deleteRootFolder(id: string) {
    method getDelayProfiles (line 148) | async getDelayProfiles() {
    method createDelayProfile (line 152) | async createDelayProfile(profile: any) {
    method updateDelayProfile (line 156) | async updateDelayProfile(id: string, data: any) {
    method deleteDelayProfile (line 160) | async deleteDelayProfile(id: string) {
    method getTags (line 164) | async getTags() {
    method createTag (line 168) | async createTag(tag: any) {
    method getDownloadClientSchema (line 173) | async getDownloadClientSchema(): Promise<DownloadClientResource[]> {
    method getDownloadClients (line 177) | async getDownloadClients(): Promise<DownloadClientResource[]> {
    method createDownloadClient (line 181) | async createDownloadClient(client: DownloadClientResource): Promise<Do...
    method updateDownloadClient (line 186) | async updateDownloadClient(id: string, client: DownloadClientResource)...
    method deleteDownloadClient (line 190) | async deleteDownloadClient(id: string): Promise<void> {
    method testDownloadClient (line 194) | async testDownloadClient(client: DownloadClientResource): Promise<any> {
    method getDownloadClientConfig (line 199) | async getDownloadClientConfig(): Promise<DownloadClientConfigResource> {
    method updateDownloadClientConfig (line 203) | async updateDownloadClientConfig(id: string, config: DownloadClientCon...
    method getRemotePathMappings (line 208) | async getRemotePathMappings(): Promise<RemotePathMappingResource[]> {
    method createRemotePathMapping (line 212) | async createRemotePathMapping(mapping: RemotePathMappingResource): Pro...
    method updateRemotePathMapping (line 216) | async updateRemotePathMapping(id: string, mapping: RemotePathMappingRe...
    method deleteRemotePathMapping (line 220) | async deleteRemotePathMapping(id: string): Promise<void> {
    method getSystemStatus (line 225) | getSystemStatus() {
    method testConnection (line 229) | async testConnection() {

FILE: src/clients/sonarr-client.ts
  type SonarrQualityProfileResource (line 16) | type SonarrQualityProfileResource = {
  class SonarrClient (line 22) | class SonarrClient implements IArrClient<QualityProfileResource, Quality...
    method constructor (line 25) | constructor(baseUrl: string, apiKey: string) {
    method initialize (line 29) | private initialize(baseUrl: string, apiKey: string) {
    method getLanguages (line 42) | async getLanguages() {
    method getQualityDefinitions (line 47) | getQualityDefinitions() {
    method updateQualityDefinitions (line 51) | async updateQualityDefinitions(definitions: QualityDefinitionResource[...
    method getQualityProfiles (line 57) | getQualityProfiles() {
    method createQualityProfile (line 61) | createQualityProfile(profile: SonarrQualityProfileResource) {
    method updateQualityProfile (line 65) | updateQualityProfile(id: string, profile: SonarrQualityProfileResource) {
    method deleteQualityProfile (line 69) | deleteQualityProfile(id: string): Promise<void> {
    method getCustomFormats (line 74) | getCustomFormats() {
    method createCustomFormat (line 78) | createCustomFormat(format: CustomFormatResource) {
    method updateCustomFormat (line 82) | updateCustomFormat(id: string, format: CustomFormatResource) {
    method deleteCustomFormat (line 86) | deleteCustomFormat(id: string) {
    method getNaming (line 90) | async getNaming() {
    method updateNaming (line 94) | async updateNaming(id: string, data: any) {
    method getMediamanagement (line 98) | async getMediamanagement() {
    method updateMediamanagement (line 102) | async updateMediamanagement(id: string, data: any) {
    method getUiConfig (line 106) | async getUiConfig(): Promise<UiConfigResource> {
    method updateUiConfig (line 110) | async updateUiConfig(id: string, data: UiConfigResource): Promise<UiCo...
    method getRootfolders (line 114) | async getRootfolders() {
    method addRootFolder (line 118) | async addRootFolder(data: any) {
    method updateRootFolder (line 122) | async updateRootFolder(id: string, data: any) {
    method deleteRootFolder (line 126) | async deleteRootFolder(id: string) {
    method getDelayProfiles (line 131) | async getDelayProfiles() {
    method createDelayProfile (line 135) | async createDelayProfile(profile: any) {
    method updateDelayProfile (line 139) | async updateDelayProfile(id: string, data: any) {
    method deleteDelayProfile (line 143) | async deleteDelayProfile(id: string) {
    method getTags (line 147) | async getTags() {
    method createTag (line 151) | async createTag(tag: any) {
    method getDownloadClientSchema (line 156) | async getDownloadClientSchema(): Promise<DownloadClientResource[]> {
    method getDownloadClients (line 160) | async getDownloadClients(): Promise<DownloadClientResource[]> {
    method createDownloadClient (line 164) | async createDownloadClient(client: DownloadClientResource): Promise<Do...
    method updateDownloadClient (line 168) | async updateDownloadClient(id: string, client: DownloadClientResource)...
    method deleteDownloadClient (line 172) | async deleteDownloadClient(id: string): Promise<void> {
    method testDownloadClient (line 176) | async testDownloadClient(client: DownloadClientResource): Promise<any> {
    method getDownloadClientConfig (line 181) | async getDownloadClientConfig(): Promise<DownloadClientConfigResource> {
    method updateDownloadClientConfig (line 185) | async updateDownloadClientConfig(id: string, config: DownloadClientCon...
    method getRemotePathMappings (line 190) | async getRemotePathMappings(): Promise<RemotePathMappingResource[]> {
    method createRemotePathMapping (line 194) | async createRemotePathMapping(mapping: RemotePathMappingResource): Pro...
    method updateRemotePathMapping (line 198) | async updateRemotePathMapping(id: string, mapping: RemotePathMappingRe...
    method deleteRemotePathMapping (line 202) | async deleteRemotePathMapping(id: string): Promise<void> {
    method getSystemStatus (line 207) | getSystemStatus() {
    method testConnection (line 211) | async testConnection() {

FILE: src/clients/unified-client.ts
  type ArrTypeToClient (line 27) | type ArrTypeToClient = {
  function getSpecificClient (line 41) | function getSpecificClient<T extends ArrType>(arrType: T): ArrTypeToClie...
  type ArrClientCustomFormat (line 153) | type ArrClientCustomFormat = {
  type ArrClientQualityDefinition (line 157) | type ArrClientQualityDefinition = {
  type ArrClientQualityProfile (line 161) | type ArrClientQualityProfile = {
  type ArrClientLanguageResource (line 167) | type ArrClientLanguageResource = {
  type IArrClient (line 173) | interface IArrClient<
  class UnifiedClient (line 233) | class UnifiedClient implements IArrClient {
    method constructor (line 237) | constructor(type: ArrType, baseUrl: string, apiKey: string) {
    method getLanguages (line 260) | async getLanguages() {
    method getQualityDefinitions (line 264) | async getQualityDefinitions() {
    method updateQualityDefinitions (line 268) | async updateQualityDefinitions(definitions: MergedQualityDefinitionRes...
    method createQualityProfile (line 272) | async createQualityProfile(profile: MergedQualityProfileResource) {
    method getQualityProfiles (line 276) | async getQualityProfiles() {
    method updateQualityProfile (line 280) | async updateQualityProfile(id: string, profile: MergedQualityProfileRe...
    method deleteQualityProfile (line 284) | async deleteQualityProfile(id: string) {
    method getCustomFormats (line 288) | async getCustomFormats() {
    method createCustomFormat (line 292) | async createCustomFormat(format: MergedCustomFormatResource) {
    method updateCustomFormat (line 296) | async updateCustomFormat(id: string, format: MergedCustomFormatResourc...
    method deleteCustomFormat (line 300) | async deleteCustomFormat(id: string) {
    method getNaming (line 304) | async getNaming() {
    method updateNaming (line 308) | async updateNaming(id: string, data: any) {
    method getMediamanagement (line 312) | async getMediamanagement() {
    method updateMediamanagement (line 316) | async updateMediamanagement(id: string, data: any) {
    method getRootfolders (line 320) | async getRootfolders() {
    method addRootFolder (line 324) | async addRootFolder(data: any) {
    method updateRootFolder (line 328) | async updateRootFolder(id: string, data: any) {
    method deleteRootFolder (line 332) | async deleteRootFolder(id: string) {
    method getDelayProfiles (line 336) | async getDelayProfiles() {
    method createDelayProfile (line 340) | async createDelayProfile(profile: any) {
    method updateDelayProfile (line 344) | async updateDelayProfile(id: string, data: any) {
    method deleteDelayProfile (line 348) | async deleteDelayProfile(id: string) {
    method getTags (line 352) | async getTags() {
    method createTag (line 356) | async createTag(tag: any) {
    method getDownloadClientSchema (line 360) | async getDownloadClientSchema() {
    method getDownloadClients (line 364) | async getDownloadClients() {
    method createDownloadClient (line 368) | async createDownloadClient(client: DownloadClientResource): Promise<Do...
    method updateDownloadClient (line 372) | async updateDownloadClient(id: string, client: DownloadClientResource)...
    method deleteDownloadClient (line 376) | async deleteDownloadClient(id: string): Promise<void> {
    method testDownloadClient (line 380) | async testDownloadClient(client: DownloadClientResource): Promise<any> {
    method getSystemStatus (line 384) | async getSystemStatus() {
    method testConnection (line 388) | async testConnection() {

FILE: src/clients/whisparr-client.ts
  type QualityProfileResource (line 21) | interface QualityProfileResource {
  class WhisparrClient (line 26) | class WhisparrClient implements IArrClient<
    method constructor (line 35) | constructor(baseUrl: string, apiKey: string) {
    method initialize (line 39) | private initialize(baseUrl: string, apiKey: string) {
    method getLanguages (line 52) | async getLanguages() {
    method getQualityDefinitions (line 57) | getQualityDefinitions() {
    method updateQualityDefinitions (line 61) | async updateQualityDefinitions(definitions: QualityDefinitionResource[...
    method getQualityProfiles (line 67) | getQualityProfiles() {
    method createQualityProfile (line 71) | async createQualityProfile(profile: QualityProfileResource): Promise<Q...
    method updateQualityProfile (line 86) | updateQualityProfile(id: string, profile: QualityProfileResource) {
    method deleteQualityProfile (line 90) | deleteQualityProfile(id: string): Promise<void> {
    method getCustomFormats (line 95) | getCustomFormats() {
    method createCustomFormat (line 99) | createCustomFormat(format: CustomFormatResource) {
    method updateCustomFormat (line 103) | updateCustomFormat(id: string, format: CustomFormatResource) {
    method deleteCustomFormat (line 107) | deleteCustomFormat(id: string) {
    method getNaming (line 111) | async getNaming() {
    method updateNaming (line 115) | async updateNaming(id: string, data: any) {
    method getMediamanagement (line 119) | async getMediamanagement() {
    method updateMediamanagement (line 123) | async updateMediamanagement(id: string, data: any) {
    method getUiConfig (line 127) | async getUiConfig(): Promise<UiConfigResource> {
    method updateUiConfig (line 131) | async updateUiConfig(id: string, data: UiConfigResource): Promise<UiCo...
    method getRootfolders (line 135) | async getRootfolders() {
    method addRootFolder (line 139) | async addRootFolder(data: any) {
    method updateRootFolder (line 143) | async updateRootFolder(id: string, data: any) {
    method deleteRootFolder (line 147) | async deleteRootFolder(id: string) {
    method getDelayProfiles (line 152) | async getDelayProfiles() {
    method createDelayProfile (line 156) | async createDelayProfile(profile: any) {
    method updateDelayProfile (line 160) | async updateDelayProfile(id: string, data: any) {
    method deleteDelayProfile (line 164) | async deleteDelayProfile(id: string) {
    method getTags (line 168) | async getTags() {
    method createTag (line 172) | async createTag(tag: any) {
    method getDownloadClientSchema (line 177) | async getDownloadClientSchema(): Promise<DownloadClientResource[]> {
    method getDownloadClients (line 181) | async getDownloadClients(): Promise<DownloadClientResource[]> {
    method createDownloadClient (line 185) | async createDownloadClient(client: DownloadClientResource): Promise<Do...
    method updateDownloadClient (line 190) | async updateDownloadClient(id: string, client: DownloadClientResource)...
    method deleteDownloadClient (line 194) | async deleteDownloadClient(id: string): Promise<void> {
    method testDownloadClient (line 198) | async testDownloadClient(client: DownloadClientResource): Promise<any> {
    method getDownloadClientConfig (line 203) | async getDownloadClientConfig(): Promise<DownloadClientConfigResource> {
    method updateDownloadClientConfig (line 207) | async updateDownloadClientConfig(id: string, config: DownloadClientCon...
    method getRemotePathMappings (line 212) | async getRemotePathMappings(): Promise<RemotePathMappingResource[]> {
    method createRemotePathMapping (line 216) | async createRemotePathMapping(mapping: RemotePathMappingResource): Pro...
    method updateRemotePathMapping (line 220) | async updateRemotePathMapping(id: string, mapping: RemotePathMappingRe...
    method deleteRemotePathMapping (line 224) | async deleteRemotePathMapping(id: string): Promise<void> {
    method getSystemStatus (line 229) | getSystemStatus() {
    method testConnection (line 233) | async testConnection() {

FILE: src/config.ts
  method resolve (line 59) | resolve(str: string) {
  method resolve (line 67) | resolve(str: string) {
  method resolve (line 83) | resolve(path: string) {
  type MergedScoreInfo (line 630) | type MergedScoreInfo = {

FILE: src/delay-profiles.ts
  function flattenDelayProfiles (line 19) | function flattenDelayProfiles<T extends { tags?: number[] | null }>(dela...
  function splitServerDelayProfiles (line 27) | function splitServerDelayProfiles(serverProfiles: MergedDelayProfileReso...
  type ComparisonKeys (line 120) | type ComparisonKeys = keyof Pick<

FILE: src/downloadClientConfig/downloadClientConfig.types.ts
  type DownloadClientConfigSyncResult (line 6) | type DownloadClientConfigSyncResult = {

FILE: src/downloadClientConfig/downloadClientConfigSyncer.ts
  function normalizeConfigFields (line 18) | function normalizeConfigFields(configFields: InputConfigDownloadClientCo...
  function filterFieldsByArrType (line 35) | function filterFieldsByArrType(fields: Record<string, any>, arrType: Arr...
  function configHasChanges (line 75) | function configHasChanges(serverConfig: Record<string, any>, desiredConf...
  function syncDownloadClientConfig (line 87) | async function syncDownloadClientConfig(

FILE: src/downloadClients/downloadClientBase.test.ts
  class MockDownloadClientSync (line 11) | class MockDownloadClientSync extends BaseDownloadClientSync {
    method constructor (line 12) | constructor() {
    method testValidateDownloadClient (line 16) | public testValidateDownloadClient(config: InputConfigDownloadClient, s...
    method testResolveTagNamesToIds (line 20) | public testResolveTagNamesToIds(tagNames: (string | number)[], serverT...
    method testNormalizeConfigFields (line 24) | public testNormalizeConfigFields(configFields: Record<string, any>, ar...
    method testGetApi (line 28) | public testGetApi(): IArrClient {
    method getArrType (line 32) | protected getArrType(): ArrType {
    method calculateDiff (line 36) | protected async calculateDiff(
    method resolveConfig (line 50) | public async resolveConfig(
    method createClient (line 59) | protected createClient() {
    method updateClient (line 63) | protected updateClient() {
    method deleteClient (line 67) | protected deleteClient() {

FILE: src/downloadClients/downloadClientBase.ts
  constant PRIORITY_MIN (line 19) | const PRIORITY_MIN = 1;
  constant PRIORITY_MAX (line 20) | const PRIORITY_MAX = 50;
  constant NAME_MAX_LENGTH (line 21) | const NAME_MAX_LENGTH = 100;
  method getApi (line 44) | protected getApi(): IArrClient {
  method normalizeConfigFields (line 67) | public normalizeConfigFields(configFields: Record<string, unknown>, arrT...
  method resolveTagNamesToIds (line 84) | public resolveTagNamesToIds(tagNames: (string | number)[], serverTags: T...
  method findImplementationInSchema (line 104) | protected findImplementationInSchema(schema: DownloadClientResource[], i...
  method mergeFieldsWithSchema (line 108) | protected mergeFieldsWithSchema(
  method validateDownloadClientConfig (line 125) | protected validateDownloadClientConfig(config: unknown): {
  method validateDownloadClient (line 142) | public validateDownloadClient(config: InputConfigDownloadClient, schema:...
  method getDownloadClientSchema (line 187) | protected async getDownloadClientSchema(cache: ServerCache): Promise<Dow...
  method filterUnmanagedClients (line 198) | public filterUnmanagedClients(
  method validateConfigClients (line 221) | private async validateConfigClients(
  method createMissingTags (line 277) | private async createMissingTags(configClients: InputConfigDownloadClient...
  method createClients (line 306) | private async createClients(configs: InputConfigDownloadClient[], server...
  method updateClients (line 335) | private async updateClients(updates: DownloadClientDiff["update"], serve...
  method deleteUnmanagedClients (line 366) | private async deleteUnmanagedClients(unmanagedClients: DownloadClientRes...
  method syncDownloadClients (line 393) | public async syncDownloadClients(config: MergedConfigInstance, serverCac...

FILE: src/downloadClients/downloadClientGeneric.ts
  class GenericDownloadClientSync (line 9) | class GenericDownloadClientSync extends BaseDownloadClientSync {
    method constructor (line 10) | constructor(private arrType: ArrType) {
    method getArrType (line 14) | protected getArrType(): ArrType {
    method calculateDiff (line 130) | async calculateDiff(
    method resolveConfig (line 165) | async resolveConfig(

FILE: src/downloadClients/downloadClientSyncer.test.ts
  type TestDownloadClientResource (line 9) | type TestDownloadClientResource = Omit<DownloadClientResource, "protocol...

FILE: src/downloadClients/downloadClientSyncer.ts
  function createDownloadClientSync (line 8) | function createDownloadClientSync(arrType: ArrType): BaseDownloadClientS...
  function syncDownloadClients (line 12) | async function syncDownloadClients(

FILE: src/env.ts
  constant DEFAULT_ROOT_PATH (line 4) | const DEFAULT_ROOT_PATH = path.resolve(process.cwd());
  constant CONFIGARR_VERSION (line 8) | const CONFIGARR_VERSION = process.env.CONFIGARR_VERSION ?? "dev";
  constant BUILD_TIME (line 9) | const BUILD_TIME = process.env.BUILD_TIME ?? "";
  constant GITHUB_RUN_ID (line 10) | const GITHUB_RUN_ID = process.env.GITHUB_RUN_ID ?? "";
  constant GITHUB_REPO (line 11) | const GITHUB_REPO = process.env.GITHUB_REPO ?? "";
  constant GITHUB_SHA (line 12) | const GITHUB_SHA = process.env.GITHUB_SHA ?? "";
  function initEnvs (line 80) | function initEnvs() {

FILE: src/ky-client.ts
  function toErrorMessage (line 7) | function toErrorMessage(value: unknown): string {
  type KyResponse (line 15) | type KyResponse<Data> = Response & {
  type ResponsePromise (line 19) | type ResponsePromise<Data> = {
  type ResponseFormat (line 27) | type ResponseFormat = keyof Omit<Body, "body" | "bodyUsed">;
  type QueryParamsType (line 30) | type QueryParamsType = Record<string | number, unknown>;
  type FullRequestParams (line 32) | interface FullRequestParams extends Omit<KyOptions, "json" | "body" | "s...
  type RequestParams (line 47) | type RequestParams = Omit<FullRequestParams, "body" | "method" | "query"...
  type ApiConfig (line 49) | interface ApiConfig<SecurityDataType = unknown> extends Omit<KyOptions, ...
  type ContentType (line 55) | enum ContentType {
  class HttpClient (line 62) | class HttpClient<SecurityDataType = unknown> {
    method constructor (line 69) | constructor({ securityWorker, secure, format, ...options }: ApiConfig<...
    method mergeRequestParams (line 80) | protected mergeRequestParams(params1: KyOptions, params2?: KyOptions):...
    method stringifyFormItem (line 91) | protected stringifyFormItem(formItem: unknown) {
    method createFormData (line 99) | protected createFormData(input: Record<string, unknown>): FormData {

FILE: src/metadataProfiles/metadataProfile.types.ts
  type BaseMetadataProfileResource (line 5) | interface BaseMetadataProfileResource {
  type MetadataProfileDiff (line 12) | interface MetadataProfileDiff<T extends BaseMetadataProfileResource = an...
  type MetadataProfileSyncResult (line 18) | interface MetadataProfileSyncResult {

FILE: src/metadataProfiles/metadataProfileBase.ts
  method syncMetadataProfiles (line 28) | async syncMetadataProfiles(config: MergedConfigInstance, serverCache: Se...
  method performSync (line 54) | private async performSync(profiles: InputConfigMetadataProfile[], server...
  method performDeletion (line 91) | private async performDeletion(

FILE: src/metadataProfiles/metadataProfileLidarr.ts
  class LidarrMetadataProfileSync (line 9) | class LidarrMetadataProfileSync extends BaseMetadataProfileSync<Metadata...
    method getArrType (line 12) | protected getArrType(): "LIDARR" {
    method createMetadataProfile (line 16) | protected createMetadataProfile(resolvedConfig: MetadataProfileResourc...
    method updateMetadataProfile (line 20) | protected updateMetadataProfile(id: string, resolvedConfig: MetadataPr...
    method deleteProfile (line 24) | protected deleteProfile(id: string): Promise<void> {
    method loadFromServer (line 28) | protected async loadFromServer(): Promise<MetadataProfileResource[]> {
    method validateProfile (line 32) | private validateProfile(config: InputConfigLidarrMetadataProfile): void {
    method validateAllProfiles (line 55) | private validateAllProfiles(profiles: InputConfigMetadataProfile[]): v...
    method resolveConfig (line 71) | public async resolveConfig(config: InputConfigMetadataProfile, serverC...
    method isConfigEqual (line 169) | private isConfigEqual(
    method calculateDiff (line 253) | async calculateDiff(

FILE: src/metadataProfiles/metadataProfileReadarr.ts
  class ReadarrMetadataProfileSync (line 10) | class ReadarrMetadataProfileSync extends BaseMetadataProfileSync<Metadat...
    method getArrType (line 13) | protected getArrType(): "READARR" {
    method createMetadataProfile (line 17) | protected createMetadataProfile(resolvedConfig: MetadataProfileResourc...
    method updateMetadataProfile (line 21) | protected updateMetadataProfile(id: string, resolvedConfig: MetadataPr...
    method deleteProfile (line 25) | protected deleteProfile(id: string): Promise<void> {
    method normalizeReadarrAllowedLanguages (line 29) | private normalizeReadarrAllowedLanguages(value: string | string[] | nu...
    method loadFromServer (line 70) | protected async loadFromServer(): Promise<MetadataProfileResource[]> {
    method resolveConfig (line 74) | public async resolveConfig(config: InputConfigMetadataProfile, serverC...
    method isConfigEqual (line 123) | private isConfigEqual(resolvedConfig: MetadataProfileResource, serverP...
    method calculateDiff (line 150) | async calculateDiff(

FILE: src/metadataProfiles/metadataProfileSyncer.ts
  function createMetadataProfileSync (line 10) | function createMetadataProfileSync(arrType: ArrType): BaseMetadataProfil...
  function syncMetadataProfiles (line 26) | async function syncMetadataProfiles(arrType: ArrType, config: MergedConf...

FILE: src/quality-definitions.ts
  function interpolateSize (line 98) | function interpolateSize(min: number, max: number, pref: number, ratio: ...

FILE: src/recyclarr-importer.ts
  constant DEFAULT_RECYCLARR_GIT_URL (line 9) | const DEFAULT_RECYCLARR_GIT_URL = "https://github.com/recyclarr/config-t...

FILE: src/remotePaths/remotePath.types.ts
  type RemotePathSyncResult (line 23) | interface RemotePathSyncResult {
  type RemotePathMappingResource (line 35) | interface RemotePathMappingResource {
  type RemotePathDiff (line 45) | interface RemotePathDiff {

FILE: src/remotePaths/remotePathSyncer.ts
  function normalizePath (line 12) | function normalizePath(path: string): string {
  function createCompositeKey (line 20) | function createCompositeKey(host: string, remotePath: string): string {
  function calculateDiff (line 27) | function calculateDiff(configs: InputConfigRemotePath[], serverMappings:...
  function syncRemotePaths (line 75) | async function syncRemotePaths(arrType: ArrType, config: MergedConfigIns...

FILE: src/rootFolder/rootFolder.types.ts
  type RootFolderDiff (line 5) | interface RootFolderDiff<TConfig extends InputConfigRootFolder = InputCo...
  type RootFolderSyncResult (line 11) | interface RootFolderSyncResult {

FILE: src/rootFolder/rootFolderBase.ts
  method syncRootFolders (line 18) | async syncRootFolders(rootFolders: TConfig[], serverCache: ServerCache):...
  method loadRootFoldersFromServer (line 64) | protected async loadRootFoldersFromServer(): Promise<MergedRootFolderRes...
  class GenericRootFolderSync (line 73) | class GenericRootFolderSync extends BaseRootFolderSync<InputConfigRootFo...
    method constructor (line 76) | constructor(private arrType: ArrType) {
    method getArrType (line 80) | protected getArrType(): ArrType {
    method resolveRootFolderConfig (line 84) | public async resolveRootFolderConfig(config: InputConfigRootFolder, se...
    method calculateDiff (line 93) | async calculateDiff(
    method loadRootFoldersFromServer (line 159) | protected async loadRootFoldersFromServer(): Promise<MergedRootFolderR...

FILE: src/rootFolder/rootFolderLidarr.ts
  class LidarrRootFolderSync (line 18) | class LidarrRootFolderSync extends BaseRootFolderSync<InputConfigRootFol...
    method getArrType (line 21) | protected getArrType(): "LIDARR" {
    method resolveRootFolderConfig (line 25) | public async resolveRootFolderConfig(config: InputConfigRootFolderLida...
    method isRootFolderConfigEqual (line 103) | private isRootFolderConfigEqual(resolvedConfig: RootFolderResource, se...
    method calculateDiff (line 138) | async calculateDiff(

FILE: src/rootFolder/rootFolderReadarr.ts
  class ReadarrRootFolderSync (line 17) | class ReadarrRootFolderSync extends BaseRootFolderSync<InputConfigRootFo...
    method getArrType (line 20) | protected getArrType(): "READARR" {
    method resolveRootFolderConfig (line 24) | public async resolveRootFolderConfig(config: InputConfigRootFolderRead...
    method isRootFolderConfigEqual (line 116) | private isRootFolderConfigEqual(resolvedConfig: RootFolderResource, se...
    method calculateDiff (line 162) | async calculateDiff(

FILE: src/rootFolder/rootFolderSyncer.ts
  function createRootFolderSync (line 9) | function createRootFolderSync(arrType: ArrType): BaseRootFolderSync {
  function syncRootFolders (line 20) | async function syncRootFolders(

FILE: src/telemetry.ts
  type TelemetryConfig (line 7) | interface TelemetryConfig {
  type TelemetryData (line 11) | interface TelemetryData {
  class Telemetry (line 73) | class Telemetry {
    method isEnabled (line 78) | public static isEnabled(config?: TelemetryConfig): boolean {
    method constructor (line 86) | constructor(config?: TelemetryConfig) {
    method track (line 93) | private async track(eventName: string, data: TelemetryData) {
    method trackFeatureUsage (line 128) | public trackFeatureUsage(globalConfig: InputConfigSchema, instances: R...
    method trackInstanceConfig (line 136) | public trackInstanceConfig(instanceConfig: MergedConfigInstance, arrTy...
    method finalizeTracking (line 166) | public async finalizeTracking(): Promise<void> {
    method updateTelemetryFromInstance (line 179) | private updateTelemetryFromInstance(instanceConfig: MergedConfigInstan...
    method collectTelemetryData (line 250) | private collectTelemetryData(globalConfig: InputConfigSchema, instance...
  function getTelemetryInstance (line 339) | function getTelemetryInstance(config?: TelemetryConfig): Telemetry {
  function resetTelemetryInstance (line 347) | function resetTelemetryInstance(): void {

FILE: src/trash-guide.ts
  constant DEFAULT_TRASH_GIT_URL (line 25) | const DEFAULT_TRASH_GIT_URL = "https://github.com/TRaSH-Guides/Guides";

FILE: src/types/common.types.ts
  type DynamicImportType (line 5) | type DynamicImportType<T> = { default: T };
  type RequireAtLeastOne (line 7) | type RequireAtLeastOne<T> = {
  type UserFriendlyField (line 12) | type UserFriendlyField = {
  type CustomFormatImportImplementation (line 22) | type CustomFormatImportImplementation =
  type TC1 (line 31) | type TC1 = OmitTyped<MergedCustomFormatSpecificationSchema, "fields"> & {
  type TC2 (line 36) | type TC2 = OmitTyped<MergedCustomFormatSpecificationSchema, "fields"> & {
  type TCM (line 41) | type TCM = TC1 | TC2;
  type ImportCF (line 43) | type ImportCF = OmitTyped<MergedCustomFormatResource, "specifications"> & {
  type ConfigarrCFMeta (line 47) | type ConfigarrCFMeta = {
  type ConfigarrCF (line 52) | type ConfigarrCF = ConfigarrCFMeta & ImportCF;
  type CFConfigGroup (line 54) | type CFConfigGroup = {
  type CFIDToConfigGroup (line 59) | type CFIDToConfigGroup = Map<string, CFConfigGroup>;
  type CFProcessing (line 61) | type CFProcessing = {
  type MappedTemplates (line 67) | type MappedTemplates = Partial<
  type MappedMergedTemplates (line 89) | type MappedMergedTemplates = MappedTemplates & Required<Pick<MappedTempl...
  type ArrType (line 92) | type ArrType = (typeof ArrTypeConst)[number];
  type QualityDefinitionsSonarr (line 94) | type QualityDefinitionsSonarr = "anime" | "series" | "custom";
  type QualityDefinitionsRadarr (line 95) | type QualityDefinitionsRadarr = "movie" | "sqp-streaming" | "sqp-uhd" | ...

FILE: src/types/config.types.ts
  type CustomFormatDefinitions (line 4) | type CustomFormatDefinitions = (TrashCF | ConfigarrCF)[];
  type InputConfigSchema (line 6) | type InputConfigSchema = {
  type InputConfigCustomFormat (line 54) | type InputConfigCustomFormat = {
  type InputConfigCustomFormatGroup (line 63) | type InputConfigCustomFormatGroup = {
  type InputConfigRootFolderLidarr (line 68) | type InputConfigRootFolderLidarr = {
  type InputConfigRootFolderReadarr (line 78) | type InputConfigRootFolderReadarr = {
  type InputConfigRootFolderGeneric (line 99) | type InputConfigRootFolderGeneric = string;
  type InputConfigRootFolder (line 101) | type InputConfigRootFolder = InputConfigRootFolderGeneric | InputConfigR...
  type InputConfigDownloadClientConfig (line 103) | type InputConfigDownloadClientConfig = {
  type InputConfigRemotePath (line 133) | interface InputConfigRemotePath {
  type InputConfigArrInstance (line 139) | type InputConfigArrInstance = {
  type InputConfigDelayProfile (line 267) | type InputConfigDelayProfile = {
  type InputConfigDownloadClient (line 280) | type InputConfigDownloadClient = {
  type MediaManagementType (line 320) | type MediaManagementType = {
  type UiConfigType (line 324) | type UiConfigType = {
  type MediaNamingApiType (line 329) | type MediaNamingApiType = {
  type MediaNamingType (line 333) | type MediaNamingType = {
  type InputConfigQualityProfile (line 352) | type InputConfigQualityProfile = {
  type InputConfigQualityProfileItem (line 378) | type InputConfigQualityProfileItem = {
  type InputConfigLidarrMetadataProfile (line 385) | type InputConfigLidarrMetadataProfile = {
  type InputConfigReadarrMetadataProfile (line 393) | type InputConfigReadarrMetadataProfile = {
  type InputConfigMetadataProfile (line 406) | type InputConfigMetadataProfile = InputConfigLidarrMetadataProfile | Inp...
  type InputConfigIncludeItem (line 408) | type InputConfigIncludeItem = {
  type ConfigSchema (line 419) | type ConfigSchema = InputConfigSchema;
  type ConfigCustomFormat (line 421) | type ConfigCustomFormat = Pick<InputConfigCustomFormat, "trash_ids"> & P...
  type ConfigCustomFormatList (line 423) | type ConfigCustomFormatList = Pick<ConfigArrInstance, "custom_formats">;
  type ConfigArrInstance (line 425) | type ConfigArrInstance = OmitTyped<InputConfigArrInstance, "custom_forma...
  type ConfigQualityProfile (line 436) | type ConfigQualityProfile = OmitTyped<Required<InputConfigQualityProfile...
  type ConfigQualityProfileItem (line 441) | type ConfigQualityProfileItem = InputConfigQualityProfileItem;
  type ConfigIncludeItem (line 443) | type ConfigIncludeItem = OmitTyped<InputConfigIncludeItem, "source"> & {
  type InputConfigInstance (line 448) | type InputConfigInstance = OmitTyped<InputConfigArrInstance, "api_key" |...
  type MergedConfigInstance (line 449) | type MergedConfigInstance = OmitTyped<ConfigArrInstance, "api_key" | "ba...

FILE: src/types/download-client.types.ts
  type DownloadClientResource (line 34) | type DownloadClientResource =
  type DownloadClientField (line 47) | type DownloadClientField =
  type DownloadClientTagResource (line 59) | type DownloadClientTagResource =
  type ValidationResult (line 66) | interface ValidationResult {
  type ConnectionTestResult (line 72) | interface ConnectionTestResult {
  type DownloadClientDiff (line 78) | type DownloadClientDiff = {
  type DownloadClientSyncResult (line 85) | interface DownloadClientSyncResult {
  type TagLike (line 91) | type TagLike = { id?: number; label?: string | null };

FILE: src/types/helper.types.ts
  type OmitTyped (line 2) | type OmitTyped<Obj extends object, Keys extends keyof Obj> = Omit<Obj, K...
  type OmitTyped2 (line 4) | type OmitTyped2<T, K extends keyof T | (string & {}) | (number & {}) | (...
  type Subset (line 6) | type Subset<K, T extends K> = T;

FILE: src/types/merged.types.ts
  type QDRMerged (line 25) | type QDRMerged = QDRSonarr & QDRRadarr;
  type QDRPickedSource (line 26) | type QDRPickedSource = OmitTyped<NonNullable<QDRMerged["quality"]>, "sou...
  type CustomQualitySource (line 27) | type CustomQualitySource<T> = {
  type OmittedQuality (line 33) | type OmittedQuality = OmitTyped<QDRMerged, "quality">;
  type MergedQualityDefinitionResource (line 35) | type MergedQualityDefinitionResource = OmittedQuality & Partial<CustomQu...
  type MergedCustomFormatResource (line 36) | type MergedCustomFormatResource = SonarrCustomFormatResource & RadarrCus...
  type MergedProfileFormatItemResource (line 37) | type MergedProfileFormatItemResource = SonarrProfileFormatItemResource &...
  type QPQIRMerged (line 39) | type QPQIRMerged = SonarrQualityProfileQualityItemResource & RadarrQuali...
  type QPQIRPickedSource (line 40) | type QPQIRPickedSource = OmitTyped<NonNullable<QPQIRMerged["quality"]>, ...
  type MergedQualityProfileQualityItemResource (line 42) | type MergedQualityProfileQualityItemResource = OmitTyped<QPQIRMerged, "i...
  type QPRMerged (line 50) | type QPRMerged = SonarrQualityProfileResource & RadarrQualityProfileReso...
  type MergedQualityProfileResource (line 52) | type MergedQualityProfileResource = OmitTyped<QPRMerged, "items"> &
  type MergedCustomFormatSpecificationSchema (line 59) | type MergedCustomFormatSpecificationSchema = RadarrCustomFormatSpecifica...
  type MergedRootFolderResource (line 60) | type MergedRootFolderResource = SonarrRootFolderResource & RadarrRootFol...
  type MergedDelayProfileResource (line 61) | type MergedDelayProfileResource = import("../__generated__/sonarr/data-c...
  type MergedTagResource (line 64) | type MergedTagResource = RadarrTagResource;

FILE: src/types/recyclarr.types.ts
  type RecyclarrCustomFormats (line 4) | type RecyclarrCustomFormats = Partial<Pick<InputConfigCustomFormat, "tra...
  type RecyclarrConfigInstance (line 6) | type RecyclarrConfigInstance = OmitTyped<ConfigArrInstance, "custom_form...
  type RecyclarrTemplates (line 10) | type RecyclarrTemplates = Partial<
  type RecyclarrArrSupported (line 14) | type RecyclarrArrSupported = Subset<ArrType, "RADARR" | "SONARR">;

FILE: src/types/trashguide.types.ts
  type TrashQualityDefinitionQuality (line 3) | type TrashQualityDefinitionQuality = {
  type TrashQualityDefinition (line 11) | type TrashQualityDefinition = {
  type TrashScores (line 17) | type TrashScores = {
  type TrashCFMeta (line 31) | type TrashCFMeta = {
  type TrashCF (line 38) | type TrashCF = TrashCFMeta & ImportCF;
  type TrashQPItem (line 40) | type TrashQPItem = {
  type TrashQP (line 46) | type TrashQP = {
  type TrashCFSpF (line 61) | type TrashCFSpF = { min: number; max: number; exceptLanguage: boolean; v...
  type TrashArrSupported (line 64) | type TrashArrSupported = (typeof TrashArrSupportedConst)[number];
  type TrashRadarrNaming (line 66) | type TrashRadarrNaming = {
  type TrashSonarrNaming (line 75) | type TrashSonarrNaming = {
  type TrashCache (line 97) | type TrashCache = {
  type TrashCFGItem (line 121) | type TrashCFGItem = {
  type TrashCustomFormatGroups (line 134) | type TrashCustomFormatGroups = {
  type TrashCFGroupMapping (line 158) | type TrashCFGroupMapping = Map<string, TrashCustomFormatGroups>;
  type TrashCFConflict (line 164) | type TrashCFConflict = {

FILE: src/uiConfigs/uiConfig.types.ts
  type UiConfigSyncResult (line 6) | interface UiConfigSyncResult {
  type UiConfigResource (line 15) | interface UiConfigResource {

FILE: src/uiConfigs/uiConfigSyncer.ts
  function hasValidId (line 12) | function hasValidId(config: Record<string, unknown>): config is UiConfig...
  function syncUiConfig (line 19) | async function syncUiConfig(arrType: ArrType, uiConfig: UiConfigType | u...

FILE: src/util.ts
  function compareCustomFormats (line 113) | function compareCustomFormats(
  function compareNaming (line 120) | function compareNaming(serverObject: any, localObject: any): ReturnType<...
  function compareMediamanagement (line 124) | function compareMediamanagement(serverObject: any, localObject: any): Re...
  function compareObjectsCarr (line 128) | function compareObjectsCarr(serverObject: any, localObject: any, parent?...
  function notEmpty (line 200) | function notEmpty<TValue>(value: TValue | null | undefined): value is TV...
  constant ROOT_PATH (line 210) | const ROOT_PATH = path.resolve(process.cwd());
  function zip (line 217) | function zip<T extends unknown[][]>(...arrays: T): Array<{ [K in keyof T...
  function zipNLength (line 242) | function zipNLength<T extends unknown[][]>(...arrays: T): Array<{ [K in ...
  function performCloneOperation (line 253) | async function performCloneOperation(gitUrl: string, rootPath: string, s...
  function pickFromConst (line 381) | function pickFromConst<T extends readonly string[], K extends T[number]>...
  function isInConstArray (line 385) | function isInConstArray<T extends readonly unknown[]>(array: T, value: u...

FILE: tests/e2e/demo-todo-app.spec.ts
  constant TODO_ITEMS (line 3) | const TODO_ITEMS = ["buy some cheese", "feed the cat", "book a doctors a...
  function createDefaultTodos (line 388) | async function createDefaultTodos(page: Page) {
  function checkNumberOfTodosInLocalStorage (line 398) | async function checkNumberOfTodosInLocalStorage(page: Page, expected: nu...
  function checkNumberOfCompletedTodosInLocalStorage (line 404) | async function checkNumberOfCompletedTodosInLocalStorage(page: Page, exp...
  function checkTodosInLocalStorage (line 410) | async function checkTodosInLocalStorage(page: Page, title: string) {
Condensed preview — 236 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,730K chars).
[
  {
    "path": ".claude/PROJECT_GUIDE.md",
    "chars": 6223,
    "preview": "# Configarr - AI Agent Quick Start Guide\n\n## Project Overview\n\n**Configarr** is a configuration and synchronization tool"
  },
  {
    "path": ".claude/settings.json",
    "chars": 506,
    "preview": "{\n  \"permissions\": {\n    \"allow\": [\n      \"Bash(pnpm test:*)\",\n      \"Skill(superpowers:requesting-code-review)\",\n      "
  },
  {
    "path": ".dockerignore",
    "chars": 111,
    "preview": "node_modules\n.git\n.gitignore\n*.md\ndist\nrepos\ndockerrepos\nplaywright-report\ntest-results\nconfig.yml\nsecrets.yml\n"
  },
  {
    "path": ".env.template",
    "chars": 260,
    "preview": "#ROOT_PATH=/app\n#CUSTOM_REPO_ROOT=/app/repos\n#CONFIG_LOCATION=/app/config/config.yml\n#SECRETS_LOCATION=/app/config/secre"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 37,
    "preview": "ko_fi: blackdark93\ngithub: blackdark\n"
  },
  {
    "path": ".github/renovate.json5",
    "chars": 1359,
    "preview": "{\n  $schema: \"https://docs.renovatebot.com/renovate-schema.json\",\n  extends: [\n    \"config:recommended\",\n    \"customMana"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 6809,
    "preview": "name: Docker Builds\n\non:\n  workflow_dispatch:\n  push:\n    branches:\n      - \"main\"\n    tags:\n      - \"v*.*.*\"\n    paths-"
  },
  {
    "path": ".github/workflows/cli-release.yml",
    "chars": 4617,
    "preview": "name: CLI Release\n\non:\n  push:\n    tags:\n      - \"v*.*.*\"\n  workflow_dispatch:\n    inputs:\n      baseline:\n        descr"
  },
  {
    "path": ".github/workflows/doc-preview.yml",
    "chars": 1583,
    "preview": "name: Documentation (Preview)\n\non:\n  pull_request:\n    branches: [main]\n    paths:\n      - docs/**\n  workflow_dispatch:\n"
  },
  {
    "path": ".github/workflows/documentation.yml",
    "chars": 1587,
    "preview": "name: Documentation\n\non:\n  push:\n    tags:\n      - \"v*.*.*\"\n    paths:\n      - docs/**\n  workflow_dispatch:\n\njobs:\n  bui"
  },
  {
    "path": ".github/workflows/lint.yml",
    "chars": 581,
    "preview": "name: CI\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches-ignore:\n      - prod\n\njobs:\n  test:\n    na"
  },
  {
    "path": ".github/workflows/release-it.yml",
    "chars": 1004,
    "preview": "name: release-it\n\non:\n  workflow_dispatch:\n\njobs:\n  release:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Generat"
  },
  {
    "path": ".gitignore",
    "chars": 2657,
    "preview": "# Created by https://www.toptal.com/developers/gitignore/api/node\n# Edit at https://www.toptal.com/developers/gitignore?"
  },
  {
    "path": ".prettierignore",
    "chars": 26,
    "preview": "pnpm-lock.yaml\ndocs/build\n"
  },
  {
    "path": ".prettierrc.js",
    "chars": 81,
    "preview": "/** @type {import(\"prettier\").Options} */\nexport default {\n  printWidth: 140,\n};\n"
  },
  {
    "path": ".release-it.json",
    "chars": 970,
    "preview": "{\n  \"npm\": false,\n  \"git\": {\n    \"commitMessage\": \"chore: release ${version}\",\n    \"requireCleanWorkingDir\": false\n  },\n"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 920,
    "preview": "{\n  \"version\": \"0.2.0\",\n\n  \"configurations\": [\n    {\n      \"command\": \"pnpm start\",\n      \"name\": \"pnpm start\",\n      \"r"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 54,
    "preview": "{\n  \"yaml.customTags\": [\"!secret\", \"!env\", \"!file\"]\n}\n"
  },
  {
    "path": "AGENTS.md",
    "chars": 6223,
    "preview": "# Configarr - AI Agent Quick Start Guide\n\n## Project Overview\n\n**Configarr** is a configuration and synchronization tool"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 29399,
    "preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\n## [1.27.0](https://github.com/raydak"
  },
  {
    "path": "CNAME",
    "chars": 33,
    "preview": "configarr.raydak.de\nconfigarr.de\n"
  },
  {
    "path": "DEV.md",
    "chars": 1128,
    "preview": "# Development related README\n\n## Compiling to binary\n\n### bun (trying)\n\n- compiles and treeshakes code already\n- `bun bu"
  },
  {
    "path": "Dockerfile",
    "chars": 2388,
    "preview": "# https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md\n# TODO because multiarch build has problems with"
  },
  {
    "path": "Dockerfile-deno.Dockerfile",
    "chars": 1788,
    "preview": "# https://github.com/denoland/deno_docker/blob/main/example/Dockerfile\n\nFROM denoland/deno:alpine-2.0.0 AS base\nWORKDIR "
  },
  {
    "path": "GEMINI.md",
    "chars": 1819,
    "preview": "## General\n\nYou are a TypeScript expert specializing in modern TS and async programming.\n\n## Focus Areas\n\n- ES6+ feature"
  },
  {
    "path": "LICENSE",
    "chars": 33886,
    "preview": "GNU AFFERO GENERAL PUBLIC LICENSE\nVersion 3, 19 November 2007\n\nCopyright (C) 2007 Free Software Foundation, Inc. <https:"
  },
  {
    "path": "README.md",
    "chars": 5047,
    "preview": "# Configarr\n\n[![Documentation](https://img.shields.io/badge/Documentation-blue)](https://configarr.de)\n[![GitHub License"
  },
  {
    "path": "config.yml.template",
    "chars": 1162,
    "preview": "trashGuideUrl: https://github.com/TRaSH-Guides/Guides\n#trashRevision: master # Optional to specify sha\nrecyclarrConfigUr"
  },
  {
    "path": "custom/cfs/custom-size-bigger-40gb.json",
    "chars": 436,
    "preview": "{\n  \"trash_id\": \"custom-size-more-40gb\",\n  \"trash_scores\": {\n    \"default\": -10000\n  },\n  \"trash_description\": \"Size: Bl"
  },
  {
    "path": "custom/cfs/de-tier-01.json",
    "chars": 1879,
    "preview": "{\n  \"trash_id\": \"de-tier-01-version1\",\n  \"trash_scores\": {},\n  \"name\": \"GER HD Rel. Group Tier 01\",\n  \"includeCustomForm"
  },
  {
    "path": "custom/cfs/de-tier-02.json",
    "chars": 4217,
    "preview": "{\n  \"trash_id\": \"de-tier-02-version1\",\n  \"trash_scores\": {},\n  \"name\": \"GER HD Rel. Group Tier 02\",\n  \"includeCustomForm"
  },
  {
    "path": "custom/cfs/de-tier-03.json",
    "chars": 1549,
    "preview": "{\n  \"trash_id\": \"de-tier-03-version1\",\n  \"trash_scores\": {},\n  \"name\": \"GER HD Rel. Group Tier 03\",\n  \"includeCustomForm"
  },
  {
    "path": "custom/cfs/lang-de-dl-2.json",
    "chars": 857,
    "preview": "{\n  \"trash_id\": \"lang-de-dl-2-version1\",\n  \"trash_scores\": {},\n  \"name\": \"German DL 2\",\n  \"includeCustomFormatWhenRenami"
  },
  {
    "path": "custom/cfs/lang-de-dl.json",
    "chars": 492,
    "preview": "{\n  \"trash_id\": \"lang-de-dl-version1\",\n  \"trash_scores\": {},\n  \"name\": \"German DL\",\n  \"includeCustomFormatWhenRenaming\":"
  },
  {
    "path": "custom/cfs/lang-de-only.json",
    "chars": 876,
    "preview": "{\n  \"trash_id\": \"lang-de-only-version1\",\n  \"trash_scores\": {},\n  \"name\": \"Language: German Only\",\n  \"includeCustomFormat"
  },
  {
    "path": "custom/cfs/lang-en-only.json",
    "chars": 886,
    "preview": "{\n  \"trash_id\": \"lang-en-only-version1\",\n  \"trash_scores\": {},\n  \"name\": \" Language: English Only\",\n  \"includeCustomForm"
  },
  {
    "path": "custom/cfs/lang-mic-dub.json",
    "chars": 494,
    "preview": "{\n  \"trash_id\": \"lang-mic-dub-version1\",\n  \"trash_scores\": {},\n  \"name\": \"MIC DUB\",\n  \"includeCustomFormatWhenRenaming\":"
  },
  {
    "path": "custom/cfs/lang-not-en-de.json",
    "chars": 763,
    "preview": "{\n  \"trash_id\": \"lang-not-en-de-version1\",\n  \"trash_scores\": {},\n  \"name\": \"Language: Not ENG/GER\",\n  \"includeCustomForm"
  },
  {
    "path": "docs/.gitignore",
    "chars": 233,
    "preview": "# Dependencies\n/node_modules\n\n# Production\n/build\n\n# Generated files\n.docusaurus\n.cache-loader\n\n# Misc\n.DS_Store\n.env.lo"
  },
  {
    "path": "docs/README.md",
    "chars": 784,
    "preview": "# Configarr documentation\n\nThis website is built using [Docusaurus](https://docusaurus.io/), a modern static website gen"
  },
  {
    "path": "docs/docs/changelog.mdx",
    "chars": 269,
    "preview": "---\nsidebar_position: 8\ndescription: \"Changelog / Version changes\"\nkeywords: [changelog, version]\ntitle: Changelog\n---\n\n"
  },
  {
    "path": "docs/docs/comparison.mdx",
    "chars": 10115,
    "preview": "---\nsidebar_position: 7\ndescription: \"Comparison of Configarr to other tools\"\nkeywords: [comparison, recyclarr, notifiar"
  },
  {
    "path": "docs/docs/concepts.md",
    "chars": 2315,
    "preview": "---\nsidebar_position: 2\ndescription: \"Basic concepts and terminology for understanding Sonarr, Radarr, and custom format"
  },
  {
    "path": "docs/docs/configuration/_category_.json",
    "chars": 95,
    "preview": "{\n  \"label\": \"Configuration\",\n  \"position\": 4,\n  \"link\": {\n    \"type\": \"generated-index\"\n  }\n}\n"
  },
  {
    "path": "docs/docs/configuration/_include/config-file-sample.yml",
    "chars": 9753,
    "preview": "# Optional: Override default repositories\n#trashGuideUrl: https://github.com/BlackDark/fork-TRASH-Guides\n#recyclarrConfi"
  },
  {
    "path": "docs/docs/configuration/_include/unmanaged-customformats.yml",
    "chars": 441,
    "preview": "sonarr:\n  instance1:\n    base_url: http://sonarr:8989\n    api_key: !secret SONARR_API_KEY\n\n    # since v1.13.0. You can "
  },
  {
    "path": "docs/docs/configuration/config-file.md",
    "chars": 35620,
    "preview": "---\nsidebar_position: 2\ntitle: Configuration File\ndescription: \"Learn how to configure Configarr using config.yml, envir"
  },
  {
    "path": "docs/docs/configuration/environment-variables.md",
    "chars": 6594,
    "preview": "---\nsidebar_position: 3\ntitle: Environment Variables\ndescription: \"Learn about the environment variables used in our app"
  },
  {
    "path": "docs/docs/configuration/experimental-support.md",
    "chars": 10714,
    "preview": "---\nsidebar_position: 4\ntitle: Experimental Support\ndescription: \"Experimental and testing support for other *Arr tools\""
  },
  {
    "path": "docs/docs/configuration/general.md",
    "chars": 3526,
    "preview": "---\nsidebar_position: 1\ntitle: Basics\ndescription: \"Here we describe how configarr generally works and how things are do"
  },
  {
    "path": "docs/docs/configuration/scheduled.md",
    "chars": 1328,
    "preview": "---\nsidebar_position: 5\ntitle: Scheduling\ndescription: \"How to run configarr regulary/schedueld\"\nkeywords: [configarr co"
  },
  {
    "path": "docs/docs/configuration/telemetry.md",
    "chars": 4215,
    "preview": "---\nsidebar_position: 5\ntitle: Telemetry\ndescription: \"Learn about Configarr's anonymous telemetry and how it helps impr"
  },
  {
    "path": "docs/docs/examples.md",
    "chars": 14384,
    "preview": "---\nsidebar_position: 6\ndescription: \"Examples of Configarr usage and configuration\"\nkeywords: [configarr, examples, con"
  },
  {
    "path": "docs/docs/faq.md",
    "chars": 7466,
    "preview": "---\nsidebar_position: 7\ndescription: \"FAQ for configarr and common problems\"\nkeywords: [configarr, faq, troubleshoot]\n--"
  },
  {
    "path": "docs/docs/installation/_category_.json",
    "chars": 147,
    "preview": "{\n  \"label\": \"Installation\",\n  \"position\": 3,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Learn how t"
  },
  {
    "path": "docs/docs/installation/_include/docker-basic-conf.yml",
    "chars": 1215,
    "preview": "#trashGuideUrl: https://github.com/BlackDark/fork-TRASH-Guides\n#recyclarrConfigUrl: https://github.com/BlackDark/fork-re"
  },
  {
    "path": "docs/docs/installation/binary.md",
    "chars": 1442,
    "preview": "---\nsidebar_position: 4\ntitle: Binary\ndescription: \"Run configarr as binary file\"\nkeywords: [configarr binary, configarr"
  },
  {
    "path": "docs/docs/installation/docker.md",
    "chars": 4398,
    "preview": "---\nsidebar_position: 1\ntitle: Docker Installation\ndescription: \"Learn how to install and configure Configarr using Dock"
  },
  {
    "path": "docs/docs/installation/kubernetes.md",
    "chars": 5175,
    "preview": "---\nsidebar_position: 2\ntitle: Kubernetes Installation\ndescription: \"Learn how to install and configure Configarr using "
  },
  {
    "path": "docs/docs/installation/third-party.md",
    "chars": 7644,
    "preview": "---\nsidebar_position: 3\ntitle: Third party\ndescription: \"Learn how to install and configure Configarr in third party ser"
  },
  {
    "path": "docs/docs/intro.mdx",
    "chars": 4326,
    "preview": "---\nsidebar_position: 1\ndescription: \"Configarr - A powerful synchronization tool for Sonarr, Radarr and other *Arr tool"
  },
  {
    "path": "docs/docs/profiles/index.mdx",
    "chars": 7231,
    "preview": "---\nsidebar_position: 5\ndescription: \"Sample profiles\"\nkeywords: [configarr, examples, configuration, profiles]\n---\n\nimp"
  },
  {
    "path": "docs/docusaurus.config.ts",
    "chars": 6058,
    "preview": "import type * as Preset from \"@docusaurus/preset-classic\";\nimport type { Config } from \"@docusaurus/types\";\nimport { def"
  },
  {
    "path": "docs/package.json",
    "chars": 1230,
    "preview": "{\n  \"name\": \"configarr\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"docusaurus\": \"docusaurus\",\n    \"st"
  },
  {
    "path": "docs/sidebars.ts",
    "chars": 864,
    "preview": "import type { SidebarsConfig } from \"@docusaurus/plugin-content-docs\";\n\n// This runs in Node.js - Don't use client-side "
  },
  {
    "path": "docs/src/components/HomepageFeatures/index.tsx",
    "chars": 3315,
    "preview": "import Heading from \"@theme/Heading\";\nimport clsx from \"clsx\";\nimport styles from \"./styles.module.css\";\n\ntype FeatureIt"
  },
  {
    "path": "docs/src/components/HomepageFeatures/styles.module.css",
    "chars": 138,
    "preview": ".features {\n  display: flex;\n  align-items: center;\n  padding: 2rem 0;\n  width: 100%;\n}\n\n.featureSvg {\n  height: 200px;\n"
  },
  {
    "path": "docs/src/css/custom.css",
    "chars": 2058,
    "preview": "/**\n * Any CSS included here will be global. The classic template\n * bundles Infima by default. Infima is a CSS framewor"
  },
  {
    "path": "docs/src/pages/index.module.css",
    "chars": 420,
    "preview": "/**\n * CSS files with the .module.css suffix will be treated as CSS modules\n * and scoped locally.\n */\n\n.heroBanner {\n  "
  },
  {
    "path": "docs/src/pages/index.tsx",
    "chars": 1731,
    "preview": "import Link from \"@docusaurus/Link\";\nimport useDocusaurusContext from \"@docusaurus/useDocusaurusContext\";\nimport Homepag"
  },
  {
    "path": "docs/src/pages/markdown-page.md",
    "chars": 118,
    "preview": "---\ntitle: Markdown page example\n---\n\n# Markdown page example\n\nYou don't need React to write simple standalone pages.\n"
  },
  {
    "path": "docs/static/.nojekyll",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/static/robots.txt",
    "chars": 66,
    "preview": "User-agent: *\nDisallow:\nSitemap: https://configarr.de/sitemap.xml\n"
  },
  {
    "path": "docs/tsconfig.json",
    "chars": 176,
    "preview": "{\n  // This file is not used in compilation. It is here just for a nice editor experience.\n  \"extends\": \"@docusaurus/tsc"
  },
  {
    "path": "esbuild.ts",
    "chars": 1167,
    "preview": "import esbuild from \"esbuild\";\n\nconst externalizedModules = {};\n\n// Get build-time constants from environment variables "
  },
  {
    "path": "examples/full/.gitignore",
    "chars": 33,
    "preview": "!config/*.yml\ndockerrepos/\ndata/\n"
  },
  {
    "path": "examples/full/README.md",
    "chars": 904,
    "preview": "# Configarr - Full example\n\nThis example contains every feature provided by configarr.\n\n1. Start arr containers with `do"
  },
  {
    "path": "examples/full/cfs/custom-size-bigger-40gb.json",
    "chars": 525,
    "preview": "{\n  \"trash_id\": \"custom-size-more-40gb\",\n  \"trash_scores\": {\n    \"default\": -10000\n  },\n  \"trash_description\": \"Size: Bl"
  },
  {
    "path": "examples/full/docker-compose.jobs.yml",
    "chars": 314,
    "preview": "services:\n  configarr:\n    image: ghcr.io/raydak-labs/configarr:latest\n    networks:\n      - configarr-full\n    volumes:"
  },
  {
    "path": "examples/full/docker-compose.local.yml",
    "chars": 655,
    "preview": "services:\n  configarr:\n    #image: ghcr.io/raydak-labs/configarr:1.2.1\n    image: configarr:local\n    build:\n      conte"
  },
  {
    "path": "examples/full/docker-compose.yml",
    "chars": 1872,
    "preview": "services:\n  sonarr:\n    image: lscr.io/linuxserver/sonarr:4.0.17\n    networks:\n      - configarr-full\n    environment:\n "
  },
  {
    "path": "examples/full/lidarr.xml",
    "chars": 572,
    "preview": "<Config>\n  <BindAddress>*</BindAddress>\n  <Port>8686</Port>\n  <SslPort>6868</SslPort>\n  <EnableSsl>False</EnableSsl>\n  <"
  },
  {
    "path": "examples/full/radarr.xml",
    "chars": 572,
    "preview": "<Config>\n  <BindAddress>*</BindAddress>\n  <Port>7878</Port>\n  <SslPort>9898</SslPort>\n  <EnableSsl>False</EnableSsl>\n  <"
  },
  {
    "path": "examples/full/readarr.xml",
    "chars": 575,
    "preview": "<Config>\n  <BindAddress>*</BindAddress>\n  <Port>8787</Port>\n  <SslPort>6868</SslPort>\n  <EnableSsl>False</EnableSsl>\n  <"
  },
  {
    "path": "examples/full/sonarr.xml",
    "chars": 570,
    "preview": "<Config>\n  <BindAddress>*</BindAddress>\n  <Port>8989</Port>\n  <SslPort>9898</SslPort>\n  <EnableSsl>False</EnableSsl>\n  <"
  },
  {
    "path": "examples/full/templates/lidarr.yml",
    "chars": 275,
    "preview": "quality_profiles:\n  - name: ExampleProfile\n    reset_unmatched_scores:\n      enabled: true\n    upgrade:\n      allowed: t"
  },
  {
    "path": "examples/full/templates/radarr-cf.yml",
    "chars": 1567,
    "preview": "custom_formats:\n  - trash_ids:\n      # Can be copied from recyclarr\n\n      # HQ Release Groups\n      - 3a3ff47579026e76d"
  },
  {
    "path": "examples/full/templates/radarr-quality.yml",
    "chars": 476,
    "preview": "quality_profiles:\n  - name: ExampleProfile\n    reset_unmatched_scores:\n      enabled: true\n    upgrade:\n      allowed: t"
  },
  {
    "path": "examples/full/templates/readarr.yml",
    "chars": 273,
    "preview": "quality_profiles:\n  - name: ExampleProfile\n    reset_unmatched_scores:\n      enabled: true\n    upgrade:\n      allowed: t"
  },
  {
    "path": "examples/full/templates/sonarr-cf.yml",
    "chars": 897,
    "preview": "custom_formats:\n  - trash_ids:\n      # Can be copied from recyclarr\n\n      # HQ Source Groups\n      - e6258996055b9fbab7"
  },
  {
    "path": "examples/full/templates/sonarr-quality.yml",
    "chars": 424,
    "preview": "quality_profiles:\n  - name: ExampleProfile\n    reset_unmatched_scores:\n      enabled: true\n    upgrade:\n      allowed: t"
  },
  {
    "path": "examples/full/templates/whisparr.yml",
    "chars": 493,
    "preview": "quality_profiles:\n  - name: ExampleProfile\n    reset_unmatched_scores:\n      enabled: true\n    upgrade:\n      allowed: t"
  },
  {
    "path": "examples/full/whisparr.xml",
    "chars": 572,
    "preview": "<Config>\n  <BindAddress>*</BindAddress>\n  <Port>6969</Port>\n  <SslPort>9898</SslPort>\n  <EnableSsl>False</EnableSsl>\n  <"
  },
  {
    "path": "examples/scheduled/.gitignore",
    "chars": 27,
    "preview": "!config/*.yml\ndockerrepos/\n"
  },
  {
    "path": "examples/scheduled/README.md",
    "chars": 2745,
    "preview": "# Configarr - scheduled exammple\n\nThis is an example how you could run configarr in a scheduled manner outside of kubern"
  },
  {
    "path": "examples/scheduled/cron/configarr-reuse",
    "chars": 188,
    "preview": "LOGFILE_DEFAULT=/var/log/cron.log\n#CONFIGARR_FULL_PATH=/tmp/configarr/full/path\n\n* * * * * root docker compose -f /app/d"
  },
  {
    "path": "examples/scheduled/cron/configarr-run",
    "chars": 195,
    "preview": "LOGFILE_DEFAULT=/var/log/cron.log\n#CONFIGARR_FULL_PATH=/tmp/configarr/full/path\n\n* * * * * root docker compose -f /app/d"
  },
  {
    "path": "examples/scheduled/docker-compose.cron.yml",
    "chars": 1094,
    "preview": "services:\n  configarr:\n    image: ghcr.io/raydak-labs/configarr:latest\n    networks:\n      - configarr-full\n    volumes:"
  },
  {
    "path": "examples/scheduled/docker-compose.ofelia.yml",
    "chars": 576,
    "preview": "services:\n  configarr:\n    container_name: configarr-reused\n    image: ghcr.io/raydak-labs/configarr:latest\n    networks"
  },
  {
    "path": "examples/scheduled/docker-compose.yml",
    "chars": 388,
    "preview": "services:\n  radarr:\n    image: lscr.io/linuxserver/radarr:6.0.4\n    networks:\n      - configarr-full\n    environment:\n  "
  },
  {
    "path": "examples/scheduled/ofelia.ini",
    "chars": 600,
    "preview": "; Example of how to run on existing container which will be restarted \n[job-run \"run-configarr-existing-container\"]\nsche"
  },
  {
    "path": "examples/scheduled/radarr.xml",
    "chars": 572,
    "preview": "<Config>\n  <BindAddress>*</BindAddress>\n  <Port>7878</Port>\n  <SslPort>9898</SslPort>\n  <EnableSsl>False</EnableSsl>\n  <"
  },
  {
    "path": "flake.nix",
    "chars": 773,
    "preview": "{\n  description = \"Configarr flake\";\n\n  inputs = {\n    flake-parts.url = \"github:hercules-ci/flake-parts\";\n    nixpkgs.u"
  },
  {
    "path": "generate-api.ts",
    "chars": 2566,
    "preview": "import { unlinkSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { generateApi } from \"swagger-typescript-api\""
  },
  {
    "path": "package.json",
    "chars": 1301,
    "preview": "{\n  \"name\": \"configarr\",\n  \"version\": \"0.0.0\",\n  \"description\": \"\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"htt"
  },
  {
    "path": "pkgs/nix/module/config.nix",
    "chars": 2105,
    "preview": "{\n  config,\n  lib,\n  pkgs,\n  ...\n}: let\n  cfg = config.services.configarr;\nin {\n  config = lib.mkIf cfg.enable {\n    sys"
  },
  {
    "path": "pkgs/nix/module/default.nix",
    "chars": 58,
    "preview": "{\n  imports = [\n    ./config.nix\n    ./options.nix\n  ];\n}\n"
  },
  {
    "path": "pkgs/nix/module/options.nix",
    "chars": 1269,
    "preview": "{\n  lib,\n  pkgs,\n  ...\n}: {\n  options.services.configarr = {\n    config = lib.mkOption {\n      default = \"\";\n      descr"
  },
  {
    "path": "pkgs/nix/package.nix",
    "chars": 1413,
    "preview": "{\n  lib,\n  pkgs,\n  ...\n}:\npkgs.stdenvNoCC.mkDerivation (finalAttrs: {\n  buildPhase = ''\n    runHook preBuild\n    pnpm bu"
  },
  {
    "path": "playwright.config.ts",
    "chars": 2092,
    "preview": "import { defineConfig, devices } from \"@playwright/test\";\n\n/**\n * Read environment variables from file.\n * https://githu"
  },
  {
    "path": "secrets.yml.template",
    "chars": 44,
    "preview": "SONARR_API_KEY: replace-with-sonarr-api-key\n"
  },
  {
    "path": "src/__generated__/lidarr/Api.ts",
    "chars": 102591,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/lidarr/Content.ts",
    "chars": 1034,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/lidarr/Feed.ts",
    "chars": 1392,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/lidarr/Login.ts",
    "chars": 1525,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/lidarr/Logout.ts",
    "chars": 996,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/lidarr/Path.ts",
    "chars": 1003,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/lidarr/Ping.ts",
    "chars": 1364,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/lidarr/data-contracts.ts",
    "chars": 41899,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/radarr/Api.ts",
    "chars": 102874,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/radarr/Content.ts",
    "chars": 1034,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/radarr/Feed.ts",
    "chars": 1492,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/radarr/Login.ts",
    "chars": 1525,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/radarr/Logout.ts",
    "chars": 996,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/radarr/Path.ts",
    "chars": 1003,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/radarr/Ping.ts",
    "chars": 1364,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/radarr/data-contracts.ts",
    "chars": 41045,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/readarr/Api.ts",
    "chars": 101011,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/readarr/Content.ts",
    "chars": 1034,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/readarr/Feed.ts",
    "chars": 1399,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/readarr/Login.ts",
    "chars": 1525,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/readarr/Logout.ts",
    "chars": 996,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/readarr/Path.ts",
    "chars": 1003,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/readarr/Ping.ts",
    "chars": 1364,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/readarr/data-contracts.ts",
    "chars": 46842,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/sonarr/Api.ts",
    "chars": 103293,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/sonarr/Content.ts",
    "chars": 1034,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/sonarr/Feed.ts",
    "chars": 1505,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/sonarr/Login.ts",
    "chars": 1525,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/sonarr/Logout.ts",
    "chars": 996,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/sonarr/Path.ts",
    "chars": 1003,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/sonarr/Ping.ts",
    "chars": 1364,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/sonarr/data-contracts.ts",
    "chars": 43013,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/whisparr/Api.ts",
    "chars": 99397,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/whisparr/Content.ts",
    "chars": 1034,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/whisparr/Feed.ts",
    "chars": 1513,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/whisparr/Login.ts",
    "chars": 1525,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/whisparr/Logout.ts",
    "chars": 996,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/whisparr/Path.ts",
    "chars": 1003,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/whisparr/Ping.ts",
    "chars": 1055,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/__generated__/whisparr/data-contracts.ts",
    "chars": 40190,
    "preview": "/* eslint-disable */\n/* tslint:disable */\n// @ts-nocheck\n/*\n * ---------------------------------------------------------"
  },
  {
    "path": "src/cache.ts",
    "chars": 2873,
    "preview": "import {\n  MergedCustomFormatResource,\n  MergedQualityDefinitionResource,\n  MergedQualityProfileResource,\n  MergedTagRes"
  },
  {
    "path": "src/clients/lidarr-client.ts",
    "chars": 6518,
    "preview": "import { KyHttpClient } from \"../ky-client\";\nimport { Api } from \"../__generated__/lidarr/Api\";\nimport {\n  CustomFormatR"
  },
  {
    "path": "src/clients/radarr-client.ts",
    "chars": 6514,
    "preview": "import { KyHttpClient } from \"../ky-client\";\nimport { Api } from \"../__generated__/radarr/Api\";\nimport {\n  CustomFormatR"
  },
  {
    "path": "src/clients/readarr-client.ts",
    "chars": 6544,
    "preview": "import { KyHttpClient } from \"../ky-client\";\nimport { Api } from \"../__generated__/readarr/Api\";\nimport {\n  CustomFormat"
  },
  {
    "path": "src/clients/sonarr-client.ts",
    "chars": 6122,
    "preview": "import { KyHttpClient } from \"../ky-client\";\nimport { Api } from \"../__generated__/sonarr/Api\";\nimport {\n  CustomFormatR"
  },
  {
    "path": "src/clients/unified-client.ts",
    "chars": 12523,
    "preview": "import { MergedCustomFormatResource, MergedQualityDefinitionResource, MergedQualityProfileResource } from \"../types/merg"
  },
  {
    "path": "src/clients/whisparr-client.ts",
    "chars": 6696,
    "preview": "import { KyHttpClient } from \"../ky-client\";\nimport { Api } from \"../__generated__/whisparr/Api\";\nimport {\n  CustomForma"
  },
  {
    "path": "src/config.test.ts",
    "chars": 61371,
    "preview": "import { beforeEach, describe, expect, test, vi } from \"vitest\";\nimport yaml from \"yaml\";\nimport {\n  getSecrets,\n  isTra"
  },
  {
    "path": "src/config.ts",
    "chars": 39743,
    "preview": "import { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport fg from \"fast-glob\";\nimport yam"
  },
  {
    "path": "src/custom-formats.test.ts",
    "chars": 12243,
    "preview": "import fs from \"node:fs\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\nimport * as unifiedClient from "
  },
  {
    "path": "src/custom-formats.ts",
    "chars": 9111,
    "preview": "import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { MergedCustomFormatResource } from \"./types/merged.types"
  },
  {
    "path": "src/delay-profiles.test.ts",
    "chars": 7037,
    "preview": "import { describe, expect, test, vi } from \"vitest\";\nimport { MergedDelayProfileResource } from \"./types/merged.types\";\n"
  },
  {
    "path": "src/delay-profiles.ts",
    "chars": 6686,
    "preview": "import { getUnifiedClient } from \"./clients/unified-client\";\nimport { logger } from \"./logger\";\nimport { InputConfigDela"
  },
  {
    "path": "src/downloadClientConfig/downloadClientConfig.types.ts",
    "chars": 206,
    "preview": "/**\n * Download Client Configuration sync types\n * Handles instance-specific configuration for download clients\n */\n\nexp"
  },
  {
    "path": "src/downloadClientConfig/downloadClientConfigSyncer.test.ts",
    "chars": 16234,
    "preview": "import { describe, it, expect, vi, beforeEach, afterEach } from \"vitest\";\nimport { syncDownloadClientConfig } from \"./do"
  },
  {
    "path": "src/downloadClientConfig/downloadClientConfigSyncer.ts",
    "chars": 4967,
    "preview": "import { ServerCache } from \"../cache\";\nimport { RadarrClient } from \"../clients/radarr-client\";\nimport { SonarrClient }"
  },
  {
    "path": "src/downloadClients/downloadClientBase.test.ts",
    "chars": 7449,
    "preview": "import { describe, expect, test, vi, beforeEach } from \"vitest\";\nimport { BaseDownloadClientSync } from \"./downloadClien"
  },
  {
    "path": "src/downloadClients/downloadClientBase.ts",
    "chars": 16653,
    "preview": "import { z } from \"zod\";\nimport { ServerCache } from \"../cache\";\nimport { getUnifiedClient, IArrClient } from \"../client"
  },
  {
    "path": "src/downloadClients/downloadClientGeneric.test.ts",
    "chars": 15510,
    "preview": "import { beforeEach, describe, expect, test, vi } from \"vitest\";\nimport { DownloadProtocol } from \"../__generated__/rada"
  },
  {
    "path": "src/downloadClients/downloadClientGeneric.ts",
    "chars": 8367,
    "preview": "import { ServerCache } from \"../cache\";\nimport { logger } from \"../logger\";\nimport { ArrType } from \"../types/common.typ"
  },
  {
    "path": "src/downloadClients/downloadClientSyncer.test.ts",
    "chars": 12571,
    "preview": "import { describe, expect, test } from \"vitest\";\nimport type { MergedTagResource } from \"../types/merged.types\";\nimport "
  },
  {
    "path": "src/downloadClients/downloadClientSyncer.ts",
    "chars": 759,
    "preview": "import { ServerCache } from \"../cache\";\nimport { ArrType } from \"../types/common.types\";\nimport { MergedConfigInstance }"
  },
  {
    "path": "src/env.ts",
    "chars": 3503,
    "preview": "import path from \"node:path\";\nimport { z } from \"zod\";\n\nconst DEFAULT_ROOT_PATH = path.resolve(process.cwd());\n\n// Build"
  },
  {
    "path": "src/index.ts",
    "chars": 17972,
    "preview": "// those must be run first!\nimport \"dotenv/config\";\nimport { getBuildInfo, getEnvs, initEnvs } from \"./env\";\ninitEnvs();"
  },
  {
    "path": "src/ky-client.test.ts",
    "chars": 5119,
    "preview": "import { beforeEach, describe, expect, test, vi } from \"vitest\";\nimport kyDefault, { HTTPError, NormalizedOptions } from"
  },
  {
    "path": "src/ky-client.ts",
    "chars": 10399,
    "preview": "// Copied and modified from here: https://github.com/acacode/swagger-typescript-api/pull/690\nimport type { BeforeRequest"
  },
  {
    "path": "src/local-importer.ts",
    "chars": 2388,
    "preview": "import { default as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport yaml from \"yaml\";\nimport { getConfig } fro"
  },
  {
    "path": "src/logger.ts",
    "chars": 1671,
    "preview": "import { levels, pino } from \"pino\";\nimport pretty from \"pino-pretty\";\nimport { getEnvs, getHelpers } from \"./env\";\n\ncon"
  },
  {
    "path": "src/media-management.ts",
    "chars": 2030,
    "preview": "import { getUnifiedClient } from \"./clients/unified-client\";\nimport { logger } from \"./logger\";\nimport { MediaManagement"
  },
  {
    "path": "src/metadataProfiles/metadataProfile.types.ts",
    "chars": 737,
    "preview": "import { InputConfigMetadataProfile } from \"../types/config.types\";\n\n// Common interface for all metadata profile resour"
  },
  {
    "path": "src/metadataProfiles/metadataProfileBase.test.ts",
    "chars": 361,
    "preview": "import { describe, it, expect } from \"vitest\";\n\ndescribe(\"BaseMetadataProfileSync\", () => {\n  it(\"should be an abstract "
  },
  {
    "path": "src/metadataProfiles/metadataProfileBase.ts",
    "chars": 5599,
    "preview": "import { ServerCache } from \"../cache\";\nimport { getUnifiedClient, IArrClient } from \"../clients/unified-client\";\nimport"
  },
  {
    "path": "src/metadataProfiles/metadataProfileLidarr.test.ts",
    "chars": 11722,
    "preview": "import { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { LidarrMetadataProfileSync } from \"./metadataProf"
  },
  {
    "path": "src/metadataProfiles/metadataProfileLidarr.ts",
    "chars": 13136,
    "preview": "import { MetadataProfileResource, PrimaryAlbumType, ReleaseStatus, SecondaryAlbumType } from \"../__generated__/lidarr/da"
  },
  {
    "path": "src/metadataProfiles/metadataProfileReadarr.test.ts",
    "chars": 6338,
    "preview": "import { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { ReadarrMetadataProfileSync } from \"./metadataPro"
  },
  {
    "path": "src/metadataProfiles/metadataProfileReadarr.ts",
    "chars": 7163,
    "preview": "import { MetadataProfileResource } from \"../__generated__/readarr/data-contracts\";\nimport { ServerCache } from \"../cache"
  },
  {
    "path": "src/metadataProfiles/metadataProfileSyncer.ts",
    "chars": 1266,
    "preview": "import { ServerCache } from \"../cache\";\nimport { logger } from \"../logger\";\nimport { ArrType } from \"../types/common.typ"
  },
  {
    "path": "src/quality-definitions.test.ts",
    "chars": 3522,
    "preview": "import { describe, expect, test } from \"vitest\";\nimport { MergedQualityDefinitionResource } from \"./types/merged.types\";"
  },
  {
    "path": "src/quality-definitions.ts",
    "chars": 4174,
    "preview": "import path from \"node:path\";\nimport { MergedQualityDefinitionResource } from \"./types/merged.types\";\nimport { getUnifie"
  },
  {
    "path": "src/quality-profiles.test.ts",
    "chars": 58502,
    "preview": "import path from \"path\";\nimport { beforeEach, afterEach, describe, expect, test, vi } from \"vitest\";\nimport * as uclient"
  },
  {
    "path": "src/quality-profiles.ts",
    "chars": 26559,
    "preview": "import path from \"node:path\";\nimport {\n  MergedCustomFormatResource,\n  MergedProfileFormatItemResource,\n  MergedQualityD"
  },
  {
    "path": "src/recyclarr-importer.ts",
    "chars": 2948,
    "preview": "import { default as fs } from \"node:fs\";\nimport yaml from \"yaml\";\nimport { getConfig } from \"./config\";\nimport { logger "
  },
  {
    "path": "src/remotePaths/remotePath.types.test.ts",
    "chars": 1279,
    "preview": "import { describe, it, expect } from \"vitest\";\nimport { RemotePathConfigSchema } from \"./remotePath.types\";\n\ndescribe(\"R"
  },
  {
    "path": "src/remotePaths/remotePath.types.ts",
    "chars": 1364,
    "preview": "import { z } from \"zod\";\nimport { ArrType } from \"../types/common.types\";\nimport { InputConfigRemotePath } from \"../type"
  },
  {
    "path": "src/remotePaths/remotePathSyncer.test.ts",
    "chars": 8969,
    "preview": "import { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { syncRemotePaths } from \"./remotePathSyncer\";\nimp"
  },
  {
    "path": "src/remotePaths/remotePathSyncer.ts",
    "chars": 8734,
    "preview": "import { getSpecificClient } from \"../clients/unified-client\";\nimport { logger } from \"../logger\";\nimport { ArrType } fr"
  },
  {
    "path": "src/rootFolder/rootFolder.types.ts",
    "chars": 524,
    "preview": "import { InputConfigRootFolder } from \"../types/config.types\";\nimport { MergedRootFolderResource } from \"../types/merged"
  },
  {
    "path": "src/rootFolder/rootFolderBase.test.ts",
    "chars": 3284,
    "preview": "import { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { GenericRootFolderSync } from \"./rootFolderBase\";"
  },
  {
    "path": "src/rootFolder/rootFolderBase.ts",
    "chars": 5839,
    "preview": "import { MergedRootFolderResource } from \"../types/merged.types\";\nimport { ServerCache } from \"../cache\";\nimport { getUn"
  }
]

// ... and 36 more files (download for full content)

About this extraction

This page contains the full source code of the raydak-labs/configarr GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 236 files (2.4 MB), approximately 647.1k tokens, and a symbol index with 1339 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!