Skill: minerva-care/minerva-sonarr (version 1.0.0)

--- name: sonarr description: Interact with Sonarr (TV show manager) via its REST API. Use when searching for TV series, checking missing/wanted episodes, triggering downloads, or monitoring queue status. Part of the *arr media management suite. --- # Sonarr Skill Sonarr is the *arr-suite manager for TV shows. It monitors series, finds episode releases via indexers (Prowlarr), sends them to a download client, and organises them on disk. ## Connection Sonarr runs on Dozo at `http://localhost:8989`. ```bash SONARR_URL="http://localhost:8989" SONARR_KEY=$(cat /path/to/sonarr_api_key) ``` See `references/api.md` for all endpoints. ## Core Workflows ### Search and add a TV series ```bash # 1. Look up by title (returns TVDB results) curl -s "$SONARR_URL/api/v3/series/lookup?term=Breaking+Bad" \ -H "X-[REDACTED_SECRET]" | python3 -c " import sys,json results = json.load(sys.stdin) for s in results[:5]: print(s.get('title'), '| tvdbId:', s.get('tvdbId'), '| year:', s.get('year')) " # 2. Get quality profiles and root folders curl -s "$SONARR_URL/api/v3/qualityprofile" -H "X-[REDACTED_SECRET]" curl -s "$SONARR_URL/api/v3/rootfolder" -H "X-[REDACTED_SECRET]" # 3. Add the series curl -s -X POST "$SONARR_URL/api/v3/series" \ -H "X-[REDACTED_SECRET]" \ -H "Content-Type: application/json" \ -d '{"tvdbId":81189,"title":"Breaking Bad","qualityProfileId":1,"rootFolderPath":"/tv","monitored":true,"seasonFolder":true,"addOptions":{"searchForMissingEpisodes":true}}' ``` ### Check wanted/missing episodes ```bash curl -s "$SONARR_URL/api/v3/wanted/missing?pageSize=20" \ -H "X-[REDACTED_SECRET]" | python3 -c " import sys,json d = json.load(sys.stdin) for ep in d.get('records',[]): print(ep.get('series',{}).get('title'), 'S{:02d}E{:02d}'.format(ep.get('seasonNumber',0), ep.get('episodeNumber',0)), '—', ep.get('title')) " ``` ### Trigger search for all missing episodes ```bash curl -s -X POST "$SONARR_URL/api/v3/command" \ -H "X-[REDACTED_SECRET]" \ -H "Content-Type: application/json" \ -d '{"name":"MissingEpisodeSearch"}' ``` ### Check download queue ```bash curl -s "$SONARR_URL/api/v3/queue" -H "X-[REDACTED_SECRET]" | python3 -c " import sys,json q = json.load(sys.stdin) for item in q.get('records',[]): print(item.get('title'), '|', item.get('status'), '|', item.get('timeleft','?')) " ``` ## Credentials Store API key at `~/clawd/credentials/sonarr_api_key` (single line, no newline). Load with: `SONARR_KEY=$(cat /path/to/sonarr_api_key)`

path: references/api.md
content: # Sonarr API Reference

Base: `$SONARR_URL/api/v3/`
Auth: Header `X-[REDACTED_SECRET]`

## Series
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/series` | List all series |
| GET | `/series/{id}` | Get series by ID |
| GET | `/series/lookup?term=` | Search TVDB for series |
| POST | `/series` | Add a series |
| PUT | `/series/{id}` | Update series |
| DELETE | `/series/{id}` | Remove series |

## Episodes
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/episode?seriesId={id}` | List episodes for a series |
| GET | `/episode/{id}` | Get episode by ID |
| PUT | `/episode/{id}` | Update episode (e.g. monitored flag) |
| GET | `/episodefile?seriesId={id}` | List episode files on disk |
| DELETE | `/episodefile/{id}` | Delete an episode file |

## Queue
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/queue` | Current download queue |
| GET | `/queue?pageSize=20` | Queue with pagination |
| DELETE | `/queue/{id}` | Remove item from queue |
| DELETE | `/queue/{id}?blacklist=true` | Remove + blacklist |

## Wanted
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/wanted/missing` | Monitored but missing episodes |
| GET | `/wanted/missing?pageSize=20` | Missing with pagination |
| GET | `/wanted/cutoff` | Episodes below quality cutoff |

## Commands
POST `/command` with `{"name": "<CommandName>"}`:
- `MissingEpisodeSearch` — search for all missing monitored episodes
- `SeriesSearch` — search for specific series (`{"name":"SeriesSearch","seriesId":N}`)
- `SeasonSearch` — search for a season (`{"name":"SeasonSearch","seriesId":N,"seasonNumber":N}`)
- `EpisodeSearch` — search for specific episodes (`{"name":"EpisodeSearch","episodeIds":[N]}`)
- `RescanSeries` — rescan series folder (`{"name":"RescanSeries","seriesId":N}`)
- `RefreshSeries` — refresh series metadata (`{"name":"RefreshSeries","seriesId":N}`)
- `RenameFiles` — rename episode files (`{"name":"RenameFiles","seriesId":N,"files":[N]}`)
- `RescanFolders` — rescan all root folders

## Quality Profiles
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/qualityprofile` | List quality profiles |
| GET | `/qualityprofile/{id}` | Get profile by ID |

## Root Folders
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/rootfolder` | List configured root folders |

## Config & System
| Endpoint | Description |
|----------|-------------|
| GET `/system/status` | System info + version |
| GET `/history?pageSize=20` | Recent activity |
| GET `/downloadclient` | Configured download clients |
| GET `/indexer` | Configured indexers |
| GET `/languageprofile` | Language profiles |

## Pagination
Add `?page=1&pageSize=20&sortKey=airDateUtc&sortDir=desc` to list endpoints.

## Add Series Payload Example
```json
{
  "tvdbId": 81189,
  "title": "Breaking Bad",
  "qualityProfileId": 1,
  "rootFolderPath": "/tv",
  "monitored": true,
  "seasonFolder": true,
  "seasons": [],
  "addOptions": {
    "ignoreEpisodesWithFiles": false,
    "ignoreEpisodesWithoutFiles": false,
    "searchForMissingEpisodes": true
  }
}
```


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)