{"id":47594343,"url":"https://github.com/marcomc/raiplaysound-cli","last_synced_at":"2026-05-17T00:57:54.407Z","repository":{"id":338859907,"uuid":"1159377441","full_name":"marcomc/raiplaysound-cli","owner":"marcomc","description":"RaiPlaySound CLI for program discovery, listing, and incremental episode downloads","archived":false,"fork":false,"pushed_at":"2026-03-26T10:47:40.000Z","size":879,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-27T03:57:25.865Z","etag":null,"topics":["audio","bash","cli","downloader","italian","podcast","rai","rss","shell"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marcomc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-02-16T16:53:05.000Z","updated_at":"2026-03-26T10:45:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/marcomc/raiplaysound-cli","commit_stats":null,"previous_names":["marcomc/raiplaysound-cli"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/marcomc/raiplaysound-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomc%2Fraiplaysound-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomc%2Fraiplaysound-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomc%2Fraiplaysound-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomc%2Fraiplaysound-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcomc","download_url":"https://codeload.github.com/marcomc/raiplaysound-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomc%2Fraiplaysound-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audio","bash","cli","downloader","italian","podcast","rai","rss","shell"],"created_at":"2026-04-01T17:53:25.645Z","updated_at":"2026-05-17T00:57:54.388Z","avatar_url":"https://github.com/marcomc.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RaiPlaySound CLI\n\nA Python CLI for RaiPlaySound program discovery, season and episode inspection,\nincremental downloads, Rich-based transfer progress, metadata caching, RSS feed\ngeneration, and playlist generation.\n\n\u003e **Disclaimer:** RaiPlaySound CLI is an independent, community-developed\n\u003e project and is **not** affiliated with, endorsed by, or in any way officially\n\u003e connected with RAI, RaiPlaySound, or the official RaiPlaySound application.\n\u003e \"RAI\", \"RaiPlaySound\", radio station names, program names, show titles, and\n\u003e related marks remain the property of their respective owners. This tool\n\u003e references publicly accessible RaiPlaySound web resources only to help users\n\u003e inspect programs and download episodes they already have access to. It is\n\u003e provided as a free, open-source convenience utility for users who prefer a\n\u003e terminal-based workflow.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Capabilities](#capabilities)\n- [Configuration](#configuration)\n- [Usage](#usage)\n- [Development](#development)\n- [Testing](#testing)\n- [Disclaimer](#disclaimer)\n\n## Installation\n\nRequirements:\n\n- Python 3.10+\n- `yt-dlp`\n- `ffmpeg`\n\nSystem dependency example on macOS:\n\n```bash\nbrew install python yt-dlp ffmpeg\n```\n\nStandalone user install:\n\n```bash\ngit clone https://github.com/marcomc/raiplaysound-cli.git\ncd raiplaysound-cli\nmake install\n```\n\nThis installs the package into:\n\n- `~/.local/share/raiplaysound-cli/venv`\n- `~/.local/share/raiplaysound-cli/bin/raiplaysound-cli`\n\nand creates the user-facing command at:\n\n- `~/.local/bin/raiplaysound-cli`\n\nThe installed command is a small Python launcher that loads the package from\nthe local install tree. It does not rely on the exact interpreter path baked\ninto a pip-generated console script, so it keeps working if the underlying\nPython version changes or the venv is recreated.\n\nEditable development install:\n\n```bash\ngit clone https://github.com/marcomc/raiplaysound-cli.git\ncd raiplaysound-cli\nmake install-dev\n```\n\n`make install-dev` keeps the command in `~/.local/bin/raiplaysound-cli`, but\npoints it at the project-local launcher so source edits take effect immediately.\n\nRun the CLI from the user install:\n\n```bash\n~/.local/bin/raiplaysound-cli --version\n```\n\nPrint the focused top-level command overview:\n\n```bash\n~/.local/bin/raiplaysound-cli\n```\n\nUse command-specific help for detailed options:\n\n```bash\n~/.local/bin/raiplaysound-cli list --help\n~/.local/bin/raiplaysound-cli search --help\n~/.local/bin/raiplaysound-cli download --help\n```\n\nThe subcommand help screens are organized by topic and include short examples,\nso they are the best place to discover the supported flags in practice.\n\nOr run it directly from the project venv:\n\n```bash\n.venv/bin/python -m raiplaysound_cli --version\n```\n\nAlternative installs from Git:\n\n```bash\npip install \"git+https://github.com/marcomc/raiplaysound-cli.git\"\npip install --user \"git+https://github.com/marcomc/raiplaysound-cli.git\"\npipx install \"git+https://github.com/marcomc/raiplaysound-cli.git\"\n```\n\nUninstalling:\n\n| Install method | Uninstall command |\n| --- | --- |\n| `make install` | `make uninstall` |\n| `make install-dev` | `make uninstall-dev` |\n| `pip install ...` | `pip uninstall raiplaysound-cli` |\n| `pipx install ...` | `pipx uninstall raiplaysound-cli` |\n\n## Capabilities\n\n- Accepts either a RaiPlaySound `program_slug` or full `program_url`\n- Supports `list`, `search`, `download`, `repair`, and `outputs` commands\n- Lists stations, programs, seasons, and episodes\n- Searches stations, programs, locally cached seasons/groupings, and locally\n  cached episode metadata\n- Downloads episodes into `~/Music/RaiPlaySound/\u003cslug\u003e/`\n- Repairs existing local filenames from the per-show metadata cache without\n  deleting or re-downloading audio\n- Uses `yt-dlp --download-archive` for idempotent repeat runs\n- Uses RaiPlaySound episode `date_tracking` metadata for episode dates, so\n  filenames and generated feeds follow the editorial episode date rather than\n  a later technical publication date when Rai exposes both.\n- Supports audio formats `mp3`, `m4a`, `aac`, `ogg`, `opus`, `flac`, and `wav`\n- Supports season filtering, episode ID filtering, and episode URL filtering\n- Supports automatic re-download of archive-marked but missing local files\n- Generates Rich-based live per-episode download progress with megabyte size\n  tracking and aggregate transfer speed\n- Caches program catalog metadata and per-show episode metadata\n- Generates optional `feed.xml` RSS output and `playlist.m3u` playlist output\n- Downloads each program cover image into the program folder and references it\n  from generated RSS feeds\n- Keeps a `RaiPlayPodcast` `index.html` landing page in the target root with\n  program artwork, descriptions, local episode counts, latest downloaded\n  episode dates, RSS links, and Apple Podcasts app links only for programs that\n  currently have a `feed.xml`\n- Preserves the existing `KEY=VALUE` dot-config format at\n  `~/.raiplaysound-cli.conf`\n\n## Configuration\n\nThe CLI reads optional user defaults from:\n\n- `~/.raiplaysound-cli.conf`\n\nInstall the example config:\n\n```bash\ncp ./.raiplaysound-cli.conf.example ~/.raiplaysound-cli.conf\n```\n\nExample values:\n\n```bash\nTARGET_BASE=\"$HOME/Music/RaiPlaySound\"\nAUDIO_FORMAT=\"mp3\"\nJOBS=5\nFAVORITES=\"musicalbox,profili\"\nGROUP_BY=\"auto\"\nSTATION_FILTER=\"radio2\"\nCATALOG_MAX_AGE_HOURS=2160\n```\n\nCache-age defaults are intentionally different:\n\n- `METADATA_MAX_AGE_HOURS` defaults to `24` for per-show episode metadata\n- `CATALOG_MAX_AGE_HOURS` defaults to `2160` (90 days) for the full program\n  catalog used by `list programs`\n\nIf you want fresher program listings by default, lower\n`CATALOG_MAX_AGE_HOURS` in your config, for example:\n\n```bash\nCATALOG_MAX_AGE_HOURS=24\n```\n\nSupported config keys:\n\n| Config key | CLI option | Scope |\n| --- | --- | --- |\n| `AUDIO_FORMAT` | `--format` | download |\n| `JOBS` | `--jobs` | download |\n| `SEASONS_ARG` | `--season` | download, list `episodes` |\n| `GROUPS_ARG` | `--group` | download, list `episodes` |\n| `EPISODES_ARG` | `--episode-ids` | download |\n| `EPISODE_URLS_ARG` | `--episode-urls` | download |\n| `AUTO_REDOWNLOAD_MISSING` | `--missing` | download |\n| `ENABLE_LOG` | `--log` | download |\n| `DEBUG_PIDS` | `--debug-pids` | download |\n| `LOG_PATH_ARG` | `--log[=PATH]` | download |\n| `TARGET_BASE` | `--target-base` | outputs |\n| `RSS_FEED` | `--rss` / `--no-rss` | download |\n| `RSS_BASE_URL` | `--rss-base-url` | download, repair, outputs |\n| `APPLE_PODCASTS` | `--no-apple-podcasts` | outputs |\n| `PLAYLIST` | `--playlist` / `--no-playlist` | download |\n| `FORCE_REFRESH_METADATA` | `--refresh-metadata` | download |\n| `CLEAR_METADATA_CACHE` | `--clear-metadata-cache` | download |\n| `METADATA_MAX_AGE_HOURS` | `--metadata-max-age-hours` | download |\n| `FAVORITES` | `--favourites` | download |\n| `GROUP_BY` | `--group-by` | list `programs` |\n| `PODCASTS_SORTED` | `--sorted` | list `programs` |\n| `STATION_FILTER` | `--filter` | list `programs` |\n| `FORCE_REFRESH_CATALOG` | `--refresh-catalog` | list `programs` |\n| `CATALOG_MAX_AGE_HOURS` | `--catalog-max-age-hours` | list `programs` |\n| `STATIONS_DETAILED` | `--detailed` | list `stations` |\n| `SHOW_URLS` | `--show-urls` | list `episodes`, search |\n| `PAGER` | `--pager` | list, search |\n| `INPUT` | `\u003cprogram_slug\\|program_url\u003e` | download, list `seasons`, list `episodes` |\n\n`FAVORITES` accepts a comma-separated list of RaiPlaySound program slugs or\nfull program URLs. Running `raiplaysound-cli download --favourites` iterates\nthat list. If you do not pass `--season`, `--group`, `--episode-ids`, or\n`--episode-urls`, each favourite downloads only the latest season by default.\n\n`FORCE_REFRESH_CATALOG` and `CATALOG_MAX_AGE_HOURS` affect only `list programs`.\nThey do not change the per-show metadata cache used by `download` and\n`list episodes`.\n\n`RSS_BASE_URL` must be a direct file-serving base URL. The CLI builds enclosure\nURLs as:\n\n```text\n\u003cRSS_BASE_URL\u003e/\u003cprogram_slug\u003e/\u003cfilename\u003e\n```\n\nThat means ordinary browser share-page URLs with query strings are not valid\nRSS enclosure bases.\n\n## Usage\n\n## Quick Start\n\n```bash\nraiplaysound-cli list stations\nraiplaysound-cli list programs\nraiplaysound-cli search lucio dalla\nraiplaysound-cli list episodes america7\nraiplaysound-cli download america7\nraiplaysound-cli download --favourites\nraiplaysound-cli repair filenames musicalbox\nraiplaysound-cli outputs --index\n```\n\n## Common Workflows\n\n### Discover stations and programs\n\n```bash\nraiplaysound-cli list stations\nraiplaysound-cli list programs\nraiplaysound-cli list programs --filter radio2\nraiplaysound-cli list stations --detailed\n```\n\nExample output:\n\n```text\nAvailable RaiPlaySound radio stations (7):\n┏━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━┓\n┃ Name          ┃ Programs ┃ Slug         ┃ Page ┃\n┡━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━┩\n│ Rai Radio 1   │      123 │ radio1       │ open │\n│ Rai Radio 2   │      107 │ radio2       │ open │\n│ Rai Radio 3   │      198 │ radio3       │ open │\n└───────────────┴──────────┴──────────────┴──────┘\n\nNext:\n  programs for one station: raiplaysound-cli list programs --filter radio2\n```\n\n```text\nPrograms grouped alphabetically (107):\n┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━┓\n┃ Name                 ┃ Slug          ┃ Station ┃ Years     ┃ Groupings ┃ Description                  ┃ Page ┃\n┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━┩\n│ 1 M Next             │ 1mnext        │ radio2  │ 2025      │         — │ —                            │ open │\n│ 100 Volte Alberto    │ 100voltealbe… │ radio2  │ 2020-2025 │         — │ —                            │ open │\n│ Sordi                │               │         │           │           │                              │      │\n│ A qualcuno piace     │ aqualcunopia… │ radio2  │ 2025-2026 │         2 │ Un programma del mattino... │ open │\n│ Radio2               │               │         │           │           │                              │      │\n└──────────────────────┴───────────────┴─────────┴───────────┴───────────┴──────────────────────────────┴──────┘\n\nNext:\n  one station:   raiplaysound-cli list programs --filter radio2\n  one program:   raiplaysound-cli list episodes 1mnext\n  download one:  raiplaysound-cli download 1mnext\n```\n\n`list programs` intentionally prints the full table by default so the output is\npipe-friendly and easy to capture. For large catalogs, the most practical ways\nto narrow or browse the output are `--filter`, `--sorted`, or the opt-in\n`--pager` flag rather than auto-paging by default.\n\n### Search cached metadata\n\n```bash\nraiplaysound-cli search lucio\nraiplaysound-cli search burnt sugar --json\nraiplaysound-cli search radio2 --show-urls\n```\n\n`search` always queries live stations and the cached-or-refreshed global\nprogram catalog. Season/grouping and episode matches come from local caches\nthat were already populated by earlier `list` or `download` runs.\n\nIf RaiPlaySound is temporarily unavailable, `search` still returns any local\nseason/grouping and episode matches it can find from existing caches instead\nof failing outright. Live station and program sections are left empty in that\ncase, and the cache summary notes the live lookup failure.\n\nThat means:\n\n- station and program matches are available immediately\n- season/grouping matches depend on cached `list seasons` payloads\n- episode matches depend on local `.metadata-cache.tsv` files and, when\n  available, cached `list episodes` payloads\n\nWhen episode metadata is refreshed through downloads, the per-show\n`.metadata-cache.tsv` now also stores a searchable text field derived from the\nepisode JSON payload. That lets `search` match titles, authors, descriptions,\nand other metadata strings that Rai exposes for the cached episode.\n\n### Inspect seasons and episodes\n\n```bash\nraiplaysound-cli list seasons america7\nraiplaysound-cli list episodes america7\nraiplaysound-cli list episodes america7 --show-urls\nraiplaysound-cli list seasons america7 --json\nraiplaysound-cli list episodes battiti --group speciali\n```\n\nSeason listing uses a lightweight discovery path, so `list seasons` avoids\ndownload-side metadata refreshes and is typically faster than episode\ninspection or download preparation.\n\nRepeated `list seasons \u003cprogram\u003e` runs now also use a dedicated list-summary\ncache under the state directory, separate from download-side metadata, so\ngrouped programs do not need to re-enumerate every grouping on every call.\n\nFor programs that use non-season groupings on RaiPlaySound, `list seasons`\nalso reports those groupings instead of incorrectly collapsing everything into a\nflat episode list. For example, programs may expose specials, named thematic\ncollections, or year and period buckets instead of numbered seasons.\n\nGrouping discovery is now filter-first: when RaiPlaySound exposes selector\nfilters in the program JSON, the CLI treats those filters as the authoritative\ngroup source even if the site uses custom route names such as `cicli`,\n`clip`, or other product-specific paths.\n\n`list seasons` is also the long-term grouping inspector name for the CLI, even\nwhen the discovered program structure uses non-season collections.\n\nWhen a program exposes real seasons, `list seasons \u003cprogram\u003e --season \u003cn\u003e` narrows the\noutput to the requested season. For non-season groupings or flat programs,\n`--season` is rejected instead of being silently ignored.\n\nSeason selectors can be ordinary season numbers or year-style season keys such\nas `2025` when RaiPlaySound models seasons that way.\n\n`list episodes \u003cprogram\u003e` also aggregates episodes across discovered\ngroupings for grouped programs, instead of only listing the currently selected\nsubpage.\n\nEpisode listing now uses a read-only path: it can reuse an existing\n`.metadata-cache.tsv` to improve titles and dates, but it does not refresh or\nrewrite that cache during `list episodes`.\n\nRepeated `list episodes` runs also use a list-only cache keyed by the resolved\nsource scope, so repeated calls for the same program or grouping can reuse the\nprevious listing without touching download artifacts.\n\nThose list-only caches are versioned, and stale or incompatible cached payloads\nare rebuilt automatically instead of being reused indefinitely.\n\nWhen a program uses non-season groupings, `list episodes \u003cprogram\u003e --group \u003ckey\u003e`\nnarrows the output to one or more discovered grouping keys or labels. For\nexample:\n\n```bash\nraiplaysound-cli list episodes battiti --group speciali\nraiplaysound-cli list episodes profili --group speciale-lucio-dalla\n```\n\n`--group` cannot be combined with `--season`.\n\n`list seasons \u003cprogram\u003e` now renders seasons and non-season groupings in a\ntable with:\n\n- `Program`\n- `Type`\n- `Name`\n- `Episodes`\n- `Selector`\n- `Published`\n\nFor grouped programs, the footer now shows compact generic `download --group`\nexamples instead of repeating one command per discovered grouping.\n\nFor flat programs that do not expose real seasons or other groupings,\n`list episodes` does not invent a fake `S1` column. Those programs are shown\nas a plain episode list, and JSON output reports the season as `null`.\n\n`download \u003cprogram\u003e` now follows the same grouping-aware discovery path as\n`list episodes`, so grouped programs can be downloaded across their\ndiscovered collections instead of only the root subpage.\n\nDownload startup is also narrower now: episode discovery still happens across\nthe selected program or grouping, but metadata refresh is deferred until after\nepisode filtering. When you use selectors like `--group`, `--episode-ids`, or\n`--episode-urls`, the CLI refreshes metadata only for the episodes that will\nactually be downloaded.\n\nDuring that preparation phase, the CLI now prints explicit startup steps such\nas source discovery, episode enumeration, metadata refresh, and archive-file\nchecks so long grouped downloads are not silent before transfer starts.\n\nIf you prefer a batch workflow, set `FAVORITES` in\n`~/.raiplaysound-cli.conf` and run:\n\n```bash\nraiplaysound-cli download --favourites\n```\n\nThat iterates each configured favourite program. By default, seasonal\nprograms download only their latest season in this mode, matching the normal\nsingle-program default. You can still override the selection for every\nfavourite in the batch with options such as `--season all` or `--group\nspeciali`.\n\nOnce transfers begin, each per-episode progress row now shows downloaded size\nin megabytes, for example `5.0/10.0 MB`, while the overall row shows aggregate\ntransfer speed.\n\nDownload workers are now split into two stages:\n\n- `yt-dlp` workers fetch source audio plus sidecar metadata and thumbnails into\n  a hidden per-run workspace\n- a separate `ffmpeg` queue converts those completed downloads into the final\n  requested audio format and appends the archive entry only after conversion\n  succeeds\n\nThat means long local conversion or thumbnail-embedding work no longer blocks\nthe next network download from starting as soon as a download worker becomes\nfree.\n\nThe staged conversion path also preserves richer embedded tags for seasonal\nshows by restoring episode titles plus season and episode numbering from the\ndownloaded sidecar metadata.\n\nWhen RaiPlaySound exposes both an editorial episode date and a later technical\npublication date, the CLI uses the editorial `date_tracking` value from the\nepisode JSON. That date is used for the final audio filename, RSS `pubDate`,\nRSS item matching, playlist titles, and missing-file detection.\n\nWhen `--missing` is not enabled, the CLI now skips the archive/file existence\nscan entirely instead of paying that startup cost on every download.\n\n### Repair existing filenames\n\nUse `repair filenames` when local audio files were downloaded with a technical\npublication date but the metadata cache has the corrected RaiPlaySound\n`date_tracking` date.\n\nPreview changes without touching files:\n\n```bash\nraiplaysound-cli repair filenames musicalbox\nraiplaysound-cli repair filenames --favourites\n```\n\nApply the planned renames:\n\n```bash\nraiplaysound-cli repair filenames musicalbox --apply\nraiplaysound-cli repair filenames --favourites --apply\n```\n\nThe repair command matches local audio files to `.metadata-cache.tsv` by\nnormalized title. If the cache is partial, it can also use an unambiguous\n`DD/MM/YYYY` date embedded in the local title, such as\n`Musical Box del 12/04/2026`. It changes only the first date segment in the\nfilename and skips ambiguous titles or destination conflicts. When `RSS_FEED`\nor `PLAYLIST` is enabled in configuration, `--apply` also regenerates\n`feed.xml`, `playlist.m3u`, and the root `index.html`.\n\nIf the metadata cache itself needs to be refreshed first, run:\n\n```bash\nraiplaysound-cli download PROGRAM_SLUG --clear-metadata-cache --refresh-metadata --rss --playlist\n```\n\nThen run the filename repair in dry-run mode before applying it.\n\nExample output:\n\n```text\nAvailable seasons for america7 (https://www.raiplaysound.it/programmi/america7):\n  - Season 1: 71 episodes (published: 2023-2025)\n  - Season 2: 17 episodes (published: 2025-2026)\n```\n\n```text\nEpisodes for america7 (https://www.raiplaysound.it/programmi/america7):\n┏━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓\n┃ Season ┃ Date       ┃ Episode          ┃ ID               ┃ URL              ┃\n┡━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩\n│ S2     │ 2026-03-13 │ America7 S2E17   │ 692674e0-ceb7-4… │ https://www.rai… │\n│        │            │ La prima guerra  │                  │                  │\n│        │            │ A.I.             │                  │                  │\n│ S2     │ 2026-03-06 │ America7 S2E16   │ 7e2a8652-b220-4… │ https://www.rai… │\n```\n\n### Download episodes\n\n```bash\nraiplaysound-cli download [OPTIONS] \u003cprogram_slug|program_url\u003e\nraiplaysound-cli download musicalbox\nraiplaysound-cli download --format mp3 --jobs 5 musicalbox\nraiplaysound-cli download --season 1,2 america7\nraiplaysound-cli download battiti --group speciali\nraiplaysound-cli download --missing america7\n```\n\nExample completion summary:\n\n```text\nCompleted: done=1, skipped=0, errors=0\n```\n\n### Download specific episode selections\n\n```bash\nraiplaysound-cli download --episode-ids \u003cid1,id2\u003e america7\nraiplaysound-cli download --episode-url \u003cepisode-url\u003e america7\n```\n\n### Generate RSS and playlists\n\n```bash\nraiplaysound-cli download --rss --playlist musicalbox\n```\n\nThe RSS feed is written as `feed.xml`. RSS is an XML format, and `.xml` is the\nmost compatible extension for podcast clients and static file hosting.\n\nEvery download run also refreshes program-level assets in the show's folder:\nthe program details cache, the local cover image, and the root\n`~/Music/RaiPlaySound/index.html` page. The index page is titled\n`RaiPlayPodcast` and lists each program folder with artwork, title, author,\ndescription, local episode count, latest local episode date, and an RSS link\nonly when that program folder currently contains `feed.xml`. When\n`RSS_BASE_URL` is configured, each RSS link is paired with an Apple Podcasts\nlink using the `pcast://` URL scheme. iOS support for third-party podcast URL\nschemes is best-effort, so the normal RSS link remains available as a fallback.\nWhen cached episode metadata can be matched to a local file, the latest date\nfollows Rai's editorial episode date rather than the file's technical\npublication date. The generated index uses paths relative to itself, such as\n`program-slug/cover.jpg`, for local folder and artwork links. RSS links are\nshown only for program folders that currently contain `feed.xml`; when\n`RSS_BASE_URL` is configured, those RSS links point to\n`\u003cRSS_BASE_URL\u003e/\u003cprogram_slug\u003e/feed.xml`. The index generator also stores\n`apple-touch-icon.png` beside `index.html`, displays it in the page heading,\nand references it with Apple touch icon metadata, so iPhone Home Screen\nbookmarks can use the bundled RaiPlayPodcast-style icon. When the target root\nalready contains older program folders without program metadata or cover art,\nindex generation refreshes those missing assets for each folder.\n\nRegenerate local output files from the files already present on disk, without\ndownloading episodes again. Use `--target-base`, `--rss-base-url`, and\n`--no-apple-podcasts` to try alternate folders, link hosts, or index link\nbehavior without changing `~/.raiplaysound-cli.conf`. Apple Podcasts links are\nincluded by default when the index can use absolute RSS URLs; set\n`APPLE_PODCASTS=false` in config or pass `--no-apple-podcasts` to omit them.\n\n```bash\nraiplaysound-cli outputs --index\nraiplaysound-cli outputs --rss --index --rss-base-url http://podcasts.example.test/audio\nraiplaysound-cli outputs --all --no-apple-podcasts\nraiplaysound-cli outputs --target-base /tmp/RaiPlaySound --all --rss-base-url http://podcasts.example.test/audio\n```\n\nCommand forms:\n\n```bash\nraiplaysound-cli download [OPTIONS] \u003cprogram_slug|program_url\u003e\nraiplaysound-cli list \u003cstations|programs\u003e [OPTIONS]\nraiplaysound-cli list \u003cseasons|episodes\u003e [OPTIONS] \u003cprogram_slug|program_url\u003e\nraiplaysound-cli outputs [OPTIONS]\n```\n\nOutput folder contents:\n\n| File | Producer | Purpose |\n| --- | --- | --- |\n| `*.m4a` / `*.mp3` / ... | `yt-dlp` | Downloaded audio episodes |\n| `cover.*` | CLI | Local program artwork |\n| `.program-info.json` | CLI | Per-show program title, author, description, and artwork metadata |\n| `.download-archive.txt` | `yt-dlp` | Idempotency archive |\n| `.metadata-cache.tsv` | CLI | Per-show metadata cache |\n| `feed.xml` | CLI | Optional RSS 2.0 podcast feed |\n| `playlist.m3u` | CLI | Optional local playlist |\n| `*.log` | CLI | Optional run/debug log |\n\nTarget root contents:\n\n| File | Producer | Purpose |\n| --- | --- | --- |\n| `index.html` | CLI | Static browsable program index for the target root |\n| `apple-touch-icon.png` | CLI | Home Screen icon for iPhone bookmarks |\n\n## Development\n\nCommon commands:\n\n```bash\nmake install\nmake install-dev\nmake uninstall\nmake run\nmake test\nmake lint\nmake lint-docs\n```\n\nValidation currently includes:\n\n- `ruff check src tests`\n- `mypy src tests`\n- `black --check src tests`\n- `python -m py_compile src/raiplaysound_cli/*.py`\n- `pytest`\n- `markdownlint`\n\n## Testing\n\nSee [`docs/TESTING.md`](docs/TESTING.md)\nfor the full validation and regression-test guide for users and AI agents.\n\n## Disclaimer\n\nRaiPlaySound CLI is an independent, community-developed project and is not\naffiliated with, endorsed by, or officially connected with RAI, RaiPlaySound,\nor the official RaiPlaySound application. \"RAI\", \"RaiPlaySound\", radio station\nnames, program names, and related marks remain the property of their\nrespective owners.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcomc%2Fraiplaysound-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcomc%2Fraiplaysound-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcomc%2Fraiplaysound-cli/lists"}