module

ArrTop::CLI

Command-line entry point: resolves the config path, loads + validates the config, sets up logging, builds a Backend per configured entry, then either runs the live TUI (TUI) or prints a one-shot snapshot of the queue.

The default is the TUI when stdout is a terminal; a piped/redirected stdout (or --once/-1) falls back to the plain-text snapshot. The path resolution and backend construction are factored into config_path/build_backends so they can be unit-tested without touching the network or the process exit.

Constants

CONFIG_ENV = "ARR_TOP_CONFIG"

Environment variable naming the config file, consulted after --config but before the current-directory default search.

DEFAULT_CONFIG_FILES = ["config.yaml", "config.yml", "config.json"]

Config filenames searched (in order) in the current working directory when neither --config/-c nor ARR_TOP_CONFIG is given.

Log = ::Log.for("arrtop.cli")

Log source for CLI-phase messages (config load, backend construction, poll summary). Scoped like the other arrtop.<area> sources.

MEDIA_WIDTH = 24

Width the media (movie/series) name column is truncated to in the snapshot.

SIZE_WIDTH = 16

Width the SIZE column (the per-side disk / total pair) is right-aligned to in the snapshot, e.g. 44 MB / 2.1 GB / 1.5 GB / 2.1 GB.

SYSTEM_CONFIG_FILES = ["/etc/arr_top/config.yaml", "/etc/arr_top/config.yml", "/etc/arr_top/config.json"]

System-wide config paths searched (in order) after the current-directory defaults. A local ./config.* therefore overrides a system one. This is where the native package (.deb/.rpm) directs operators to place their config (copied from the shipped config.yaml.example).

TITLE_WIDTH = 40

Width the torrent (release title) column is truncated to in the snapshot.

USAGE = "arrtop — a top-like view of the Sonarr/Radarr download + import queue.\n\nusage: arrtop [-c|--config <path>] [-1|--once] [-h|--help] [-v|--version]\n\n -c, --config <path> path to the config file (YAML or JSON)\n -1, --once print a one-shot snapshot and exit (no live view)\n -h, --help show this help and exit\n -v, --version show the version and exit\n\nWith a terminal on stdout, arrtop runs a full-screen live view (a top-like\nTUI) that redraws on the `refresh` interval (config; default 2s) or the\ninstant you press a key. Press `q` (or Ctrl-C) to quit; the view resizes\nwith the terminal. When stdout is piped/redirected, or with --once, arrtop\nprints a single plain-text snapshot instead.\n\nConfig is resolved in this order:\n 1. -c/--config <path>\n 2. $#{CONFIG_ENV}\n 3. the first of ./config.yaml, ./config.yml, ./config.json that exists\n 4. the first of /etc/arr_top/config.yaml, .yml, .json that exists\n\nLogs are written to stderr at the Info level."

Usage text for -h/--help.

VALUE_FLAGS = {"--config", "-c"}

Flags that consume the following argument as their value. The argument after one of these is that flag's value and must never be mistaken for something else while scanning argv.

Class methods

build_backends(config : Config) : Array(Backend)

Builds a concrete Backend for each configured entry: sonarr → a SonarrBackend, radarr → a RadarrBackend. Order is preserved. A nil type cannot occur post-validation but is skipped defensively.

Source
config_flag(argv : Array(String)) : String | Nil

The --config/-c value from argv, or nil when the flag is absent. The argument after any value flag is skipped so it is never misread.

Source
config_path(argv : Array(String)) : String | Nil

The resolved config path, or nil when none is found. Precedence: -c/--config <path>$ARR_TOP_CONFIG (if non-blank) → the first existing of the current-directory defaults → the first existing of the /etc/arr_top system-wide defaults → nil. A local ./config.* thus overrides a system one.

Source
default_config_candidates

The ordered list of config-file candidates tried when neither --config nor $ARR_TOP_CONFIG selects a path: the current-directory defaults first, then the /etc/arr_top system-wide fallbacks. Pure — it consults no filesystem and no environment, so the search order is unit-testable.

Source
help?(argv : Array(String)) : Bool

Whether argv requests help via --help/-h.

Source
import_cell(progress : ImportProgress | Nil) : String

The IMPORT% cell for a resolved display progress: the copy percentage (e.g. 26.0%, or 100.0% for a finished season-pack episode), or when there is no progress to show (non-importing rows, pending episodes, and importing rows arrtop cannot watch). Pure, so it's unit-testable.

Source
once?(argv : Array(String)) : Bool

Whether argv forces the one-shot snapshot via --once/-1.

Source
run(argv : Array(String)) : Nil

Parses argv, loads + validates the config, polls every backend once and prints a snapshot. Errors are written to STDERR and exit non-zero.

Source
snapshot_header

The plain-text snapshot header line: the column labels aligned to the same columns as snapshot_row. Pure/ANSI-free, so it's unit-testable.

Source
snapshot_row(row : QueueRow, state : State, disk : Int64 | Nil, total : Int64, progress : ImportProgress | Nil) : String

One plain-text snapshot data line for row at effective display state, the combined disk/total size pair, and resolved import progress: media · torrent · status · size (right-aligned human_size_pair) · DL% · IMPORT%. Pure and ANSI-free, so it's unit-testable and safe for a piped/--once stdout.

Source
tui?(argv : Array(String)) : Bool

Whether to run the interactive TUI: stdout is a terminal and --once/-1 was not passed.

Source
version?(argv : Array(String)) : Bool

Whether argv requests the version via --version/-v.

Source