feat: add arr-cli skill — Radarr + Sonarr media library CLI #13

Merged
magnus merged 1 commit from feat/arr-cli-skill into main 2026-05-21 23:37:24 -04:00
Contributor

Two CLIs, one skill wrapper. radarr-cli for movies (list, lookup, calendar, collections), sonarr-cli for TV series (list, lookup, episodes, calendar, wanted).

All cli-builder patterns.

Signed-off-by: Jasper magnus@groktop.us

Two CLIs, one skill wrapper. radarr-cli for movies (list, lookup, calendar, collections), sonarr-cli for TV series (list, lookup, episodes, calendar, wanted). All cli-builder patterns. Signed-off-by: Jasper <magnus@groktop.us>
Two CLIs, one skill wrapper. radarr-cli manages movies (list, lookup,
calendar, collections), sonarr-cli manages TV series (list, lookup,
episodes, calendar, wanted). Separate API keys and server URLs per app.

All cli-builder patterns: --json, --dry-run, --quiet, --verbose,
lazy auth, emit() dual-output, structured logging, pre-parsed flags.

Signed-off-by: Jasper <magnus@groktop.us>
magnus merged commit e067d7a7ad into main 2026-05-21 23:37:24 -04:00
jasper left a comment

test

test
jasper left a comment

Automated Review — Jasper

🐛 Bug: ConnectionError will never catch request failures

Severity: Medium — Both radarr-cli and sonarr-cli catch bare ConnectionError in their _get() and _post() methods. This is the Python built-in builtins.ConnectionError, but requests raises requests.exceptions.ConnectionError on connection failures. The except clause will never fire, and the user will see an unhandled traceback instead of the friendly error message.

Fix: Change except ConnectionErrorexcept requests.exceptions.ConnectionError in all four locations (_get × 2 + _post × 2 across both files).


🎨 Style: id shadows built-in

In radarr-cli cmd_calendar(), variable id = m.get("tmdbId","") shadows Python's built-in id(). Minor, but the rest of the file uses tid or tmdb_id for TMDb IDs — keep consistent.


♻️ Duplication between CLIs

~80% shared infrastructure (_preparse, emit/die/log/warn helpers, _get/_post methods, error handling, and dry-run logic). This is acceptable per cli-builder's self-contained binary principle, but if a third arr CLI appears (Readarr, Lidarr, etc.), extract a shared arr_base.py.


📦 Dead code: _post() and add_movie()/add_series()

_post(), add_movie(), and add_series() exist but no CLI command calls them. Not an issue — useful for future expansion — but worth noting the gap if write commands are intended.


⚙️ cmd_wanted always requests page 1

cmd_wanted() calls client.wanted_missing(limit=parsed.limit) but never passes page. For users with many missing episodes, only the first page is returned. Known Gotchas documents pagination, so this is documented — but adding a --page flag would be a natural enhancement.


Overall: Solid cli-builder patterns throughout — _preparse, emit() dual-output, lazy auth, stderr hygiene. The ConnectionError bug is the one that needs fixing before merge. Everything else is style or future enhancement.

## Automated Review — Jasper ### 🐛 Bug: `ConnectionError` will never catch request failures **Severity: Medium** — Both `radarr-cli` and `sonarr-cli` catch bare `ConnectionError` in their `_get()` and `_post()` methods. This is the Python built-in `builtins.ConnectionError`, but `requests` raises `requests.exceptions.ConnectionError` on connection failures. The except clause will never fire, and the user will see an unhandled traceback instead of the friendly error message. **Fix:** Change `except ConnectionError` → `except requests.exceptions.ConnectionError` in all four locations (`_get` × 2 + `_post` × 2 across both files). --- ### 🎨 Style: `id` shadows built-in In `radarr-cli` `cmd_calendar()`, variable `id = m.get("tmdbId","")` shadows Python's built-in `id()`. Minor, but the rest of the file uses `tid` or `tmdb_id` for TMDb IDs — keep consistent. --- ### ♻️ Duplication between CLIs ~80% shared infrastructure (`_preparse`, `emit`/`die`/`log`/`warn` helpers, `_get`/`_post` methods, error handling, and dry-run logic). This is acceptable per cli-builder's self-contained binary principle, but if a third arr CLI appears (Readarr, Lidarr, etc.), extract a shared `arr_base.py`. --- ### 📦 Dead code: `_post()` and `add_movie()`/`add_series()` `_post()`, `add_movie()`, and `add_series()` exist but no CLI command calls them. Not an issue — useful for future expansion — but worth noting the gap if write commands are intended. --- ### ⚙️ `cmd_wanted` always requests page 1 `cmd_wanted()` calls `client.wanted_missing(limit=parsed.limit)` but never passes `page`. For users with many missing episodes, only the first page is returned. Known Gotchas documents pagination, so this is documented — but adding a `--page` flag would be a natural enhancement. --- **Overall:** Solid cli-builder patterns throughout — `_preparse`, `emit()` dual-output, lazy auth, stderr hygiene. The ConnectionError bug is the one that needs fixing before merge. Everything else is style or future enhancement.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
magnus/agent-skills!13
No description provided.