Posters (the downloaded bytes, per size, 30 days, at most 200 MB) and casts (people.json, 7 days, at most 2000) are stored in the user's cache directory (os.UserCacheDir()/arr-tui) and used on the next start before asking the servers. Expired posters are pruned at startup, casts are written shortly after new ones arrive and on exit. Tests turn the cache off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
149 lines
10 KiB
Markdown
149 lines
10 KiB
Markdown
# arr-tui
|
||
|
||
A terminal UI to search for movies and series with [Radarr](https://radarr.video) and
|
||
[Sonarr](https://sonarr.tv), pick releases by hand, and follow the downloads in
|
||
[SABnzbd](https://sabnzbd.org).
|
||
|
||

|
||
|
||
- **Movies / Series**: search as you type, add titles with a quality profile and root folder,
|
||
optionally start the automatic search.
|
||
- **Trending, most watched, anticipated**: while the search box is empty, Movies and Series show
|
||
lists from [Trakt](https://trakt.tv): trending now, most watched this week, anticipated, popular,
|
||
and the US box office for movies. `[` and `]` switch lists; titles already in your library are
|
||
ticked, the others can be added right there (Enter). Needs a free Trakt client ID (see Configure).
|
||
- **Library**: movies and series with their status; the dot before a title turns blue while it
|
||
is downloading, and the details say how far.
|
||
- **Cache**: posters (30 days, at most 200 MB) and casts (7 days) are kept between runs in
|
||
`~/.cache/arr-tui` (`$XDG_CACHE_HOME`; `~/Library/Caches/arr-tui` on macOS), so they show at
|
||
once after a restart. Deleting the folder is always safe.
|
||
- **Season posters**: in a series' seasons and episodes, the poster follows the selected season.
|
||
- **Cast**: with a Trakt client ID, the details pane also lists the director (or the creators of a
|
||
series) and the cast with their roles, below the plot, in every view.
|
||
- **Interactive search**: list the releases Radarr/Sonarr find (approved or rejected, with reasons),
|
||
sort and filter them (by approval, quality, x265 / x264 / AV1, HDR, Dolby Vision, audio format, language), and grab one. Series: pick a season or a single episode first.
|
||
- **Posters**: the detail panes show the poster at the top right; title, facts, path and plot
|
||
flow along its left side and continue at full width below it. In kitty and Ghostty it is a real
|
||
image at the terminal's full resolution (Kitty graphics protocol with Unicode placeholders, so
|
||
popups and dialogs cover it like text). Everywhere else it is drawn with colored block characters,
|
||
which works over SSH and in any terminal with colors. Library items use the copy stored in
|
||
Radarr/Sonarr; search results are downloaded from the metadata provider's image host (TMDb,
|
||
TheTVDB). Turn it off with `"ui": {"covers": false}`. `"ui": {"cover_style": ...}` picks the
|
||
drawing: `auto` (default: real images where the terminal is known to support them, otherwise
|
||
plain cells in macOS Terminal, sextants on terminals known to have the glyphs or when fontconfig
|
||
finds an installed font with them (not over SSH), else quadrants), `kitty` (force real images),
|
||
`sextant` (2x3 pixels per cell, needs a font with the Symbols for Legacy Computing block) or
|
||
`quadrant` (2x2, every font has them) or `cells` (one colored cell per pixel, no glyphs; for
|
||
terminals whose block characters come out uneven, like macOS Terminal). Inside tmux or screen the
|
||
block styles are used. If a poster looks wrong, set `quadrant`, or `cells` if the rows look shifted.
|
||
- **Calendar**: the next two weeks of movie releases (cinemas, digital, physical) and airing episodes
|
||
in one list grouped by day, with poster and plot. Move by weeks, include unmonitored items, search
|
||
for releases or start an automatic search from there.
|
||
- **Downloads**: SABnzbd queue and history plus the Radarr/Sonarr queues. Pause/resume, delete,
|
||
retry failed downloads, remove from the arr queue and blocklist.
|
||
- **Config (F6)**: edit everything in the config file from inside the program, in one list you move
|
||
through with the arrow keys: service addresses and API keys, the add-form defaults (quality profile and root folder, picked from the lists the server has), refresh interval, posters, theme, notifications. *Test*
|
||
checks the values you typed before saving; *Save* writes the file (permissions kept, `0600` for a
|
||
new file) and applies the changes at once, no restart. Values that come from `ARR_TUI_*`
|
||
environment variables are greyed out and are never written to the file.
|
||
- **Log (F7)**: actions report through popups that fade away; the log keeps the history.
|
||
- **Download notifications**: a popup (and a log entry) when a SABnzbd download finishes or fails,
|
||
whichever view is open. SABnzbd's history is checked every 15 seconds; downloads that finished
|
||
before arr-tui started are not announced. `"ui": {"notify_downloads": false}` turns it off,
|
||
`"bell": true` also rings the terminal bell.
|
||
- **Themes**: fixed dark and light color sets that look the same in every terminal, whatever its
|
||
color theme. `"ui": {"theme": ...}` is `auto` (default: light when the terminal reports a light
|
||
background, else dark), `dark` or `light`; it can also be switched in the Config view, which
|
||
recolors everything at once.
|
||
- Connection indicators for all three services in the top right; `F9` shows every key.
|
||
|
||
Requires Radarr/Sonarr v3+ API (Radarr 5/6, Sonarr 4) and SABnzbd 4+. Only Usenet releases are
|
||
shown for grabbing, torrents are hidden.
|
||
|
||
## Screenshots
|
||
|
||
The screenshots show a made-up library (invented titles, generated posters), taken in Ghostty,
|
||
where posters are real images.
|
||
|
||
| | |
|
||
|---|---|
|
||
|  |  |
|
||
| **Movies / Series**: search as you type | **Releases**: pick one by hand |
|
||
|  |  |
|
||
| **Seasons and episodes** of a series | **Downloads** from SABnzbd, Radarr and Sonarr |
|
||
|  |  |
|
||
| **Calendar** of the next two weeks | **Config** inside the program |
|
||
|  |  |
|
||
| **Trending, most watched, anticipated** from Trakt | **Light theme** |
|
||
|
||
## Install
|
||
|
||
```sh
|
||
go install git.stinnesbeck.com/nils/arr-tui/cmd/arr-tui@latest
|
||
```
|
||
|
||
or build from a checkout (`make build`), or `make dist` for cross-compiled binaries in `dist/`.
|
||
|
||
## Configure
|
||
|
||
Just start `arr-tui`: on the first start it creates `$XDG_CONFIG_HOME/arr-tui/config.json`
|
||
(usually `~/.config/arr-tui/config.json`, or the file given with `--config path`) and opens the
|
||
Config view (F6), where you enter the address and API key of each service and save. API keys are in
|
||
each app under Settings → General. A service left empty is not used (e.g. no SABnzbd), its indicator
|
||
stays grey. You can also write the file yourself, starting from `config.example.json`:
|
||
|
||
```json
|
||
{
|
||
"radarr": { "url": "http://localhost:7878", "apikey": "...", "default_quality_profile": "HD-1080p", "default_root_folder": "/movies" },
|
||
"sonarr": { "url": "http://localhost:8989", "apikey": "...", "default_quality_profile": "HD-1080p", "default_root_folder": "/tv" },
|
||
"sabnzbd": { "url": "http://localhost:8080", "apikey": "..." },
|
||
"ui": { "refresh_seconds": 3, "covers": true, "cover_style": "auto", "theme": "auto", "notify_downloads": true, "bell": false }
|
||
}
|
||
```
|
||
|
||
`default_*` are optional preselections in the add dialog. URL and key can also come from the
|
||
environment: `ARR_TUI_{RADARR,SONARR,SABNZBD}_{URL,APIKEY}`, which takes precedence over the file.
|
||
|
||
The trending, most watched and anticipated lists need a Trakt client ID (free, no Trakt account
|
||
of yours is touched): sign in at [trakt.tv](https://trakt.tv), create an app under
|
||
[Settings → Your API Apps → New Application](https://trakt.tv/oauth/applications/new) (any name;
|
||
redirect URI `urn:ietf:wg:oauth:2.0:oob`), and enter its **Client ID** in the Config view under
|
||
Trakt, or as `"trakt": {"client_id": "..."}` in the file, or in `ARR_TUI_TRAKT_CLIENT_ID`.
|
||
Keep the file private (`chmod 600`); it holds your API keys.
|
||
|
||
## Keys
|
||
|
||
| Key | Action |
|
||
|---|---|
|
||
| `F1`–`F7` | switch view (Movies, Series, Library, Downloads, Calendar, Config, Log) |
|
||
| `Tab`, `Shift+Tab` | switch panel within a view |
|
||
| `F9` | help |
|
||
| `/` | focus search box |
|
||
| `[`, `]`, `r` (Movies / Series, empty search) | previous / next Trakt list, reload it |
|
||
| `Enter` | add selected title |
|
||
| `i` | interactive release search |
|
||
| `Tab`, `f`, `F`, `/`, `t`, `s`, `d`, `i`/`Enter`, `r` (library) | movies/series list, status filter, file-property filter, text filter, monitor, search, remove, releases/episodes, reload |
|
||
| `[`, `]`, `t`, `u`, `Enter`, `s` (calendar) | week back / forward, today, unmonitored, releases, search |
|
||
| `Enter`, `i`, `s`, `t` (episodes) | expand season / releases, release search, search, monitor |
|
||
| `Enter`/`g`, `s`, `f`, `F` (release list) | grab, cycle sort, hide rejected, filter by properties |
|
||
| `p`, `d`, `t`, `b`, `r` (downloads) | pause, delete, retry, blocklist, refresh |
|
||
| `Esc` | back / close dialog |
|
||
| `Ctrl+C` | quit |
|
||
|
||
## Development
|
||
|
||
`dev/` has a compose file with pinned Radarr, Sonarr and SABnzbd containers plus a fake indexer;
|
||
see [dev/README.md](dev/README.md).
|
||
`make test` runs vet and the unit tests. The screenshots are made with
|
||
`dev/screenshots/take.sh` (see [its README](dev/screenshots/README.md)). The design and
|
||
milestone history are in [SPECS.md](SPECS.md).
|
||
|
||
Releases: tag and push, then `scripts/release.sh` (or `make release`) builds the binaries and publishes
|
||
them on Gitea with the matching `CHANGELOG.md` section. It needs an access token with write access
|
||
to the repository in `$GITEA_TOKEN` or `~/.config/arr-tui-release-token`; `--check` verifies
|
||
everything without publishing, `--dry-run` builds without publishing.
|
||
|
||
## License
|
||
|
||
MIT, see [LICENSE](LICENSE).
|