Skip to content

Repository files navigation

AgentP

A fast, polished podcast downloader for your terminal.

Browse feeds, select episodes, and write clean ID3 tags from an interactive TUI—or automate everything with the CLI.

CI status Crates.io version GitHub downloads GPL v3 license

Installation · Quick start · Keyboard reference · CLI reference · Configuration · Troubleshooting

AgentP browsing podcasts and selecting episodes from The AI Daily Brief, Merge Conflict, and Committing High Reason

Why AgentP?

Interactive or automated
Choose episodes in the TUI or script repeatable downloads with the CLI.
Library-ready metadata
Control album, artist, title, artwork, filenames, and numeric prefixes.
Any RSS podcast
Add a feed manually or let AgentP prepopulate its channel metadata.
Flexible selection
Download specific episodes, the latest or oldest N, or the complete feed.
Fast command palette
Press Ctrl+K to find actions without memorizing every shortcut.
Runs everywhere
One Rust binary for macOS, Linux, and Windows with a built-in Dracula theme.

Installation

Method Install
Homebrew · macOS and Linux brew install ByteMagicInc/tap/agent-p
Scoop · Windows scoop bucket add bytemagicinc https://github.com/ByteMagicInc/scoop-bucket
scoop install agent-p
Cargo · Rust 1.88+ cargo install agent-p --locked
Pre-built binary Download an archive from GitHub Releases and place agentp on your PATH.

Tip

Alpine and other minimal Linux distributions can use the fully static x86_64-unknown-linux-musl build.

Quick start

Interactive TUI

agentp

The first launch creates your configuration, seeds a set of demo podcasts, and points downloads at ~/Downloads/Podcasts so you can explore immediately:

  1. Choose a podcast and press Enter.
  2. Mark episodes with Space or select everything with a.
  3. Press Enter to download.

Press c to add your own feeds, change the download folder, and set the defaults for new podcasts.

AgentP comes with my favorite podcasts so you can see how different per-podcast configs are applied.

Scriptable CLI

agentp podcast add --feed-url <RSS_URL> --from-feed
agentp podcast list
agentp download --podcast <NAME_OR_INDEX> --latest 5

Podcast selectors accept either a 1-based index or a case-insensitive name. A subcommand always runs headlessly, and the mode flags do not change that. With no subcommand, agentp opens the TUI unless config.json sets "default_mode": "cli", and --tui or --cli (aliases --user-mode and --agent-mode) override that default for a single run, where --cli prints this help. --help works on every command and agentp --version prints the version.

See AgentP in action

Add a podcast from its RSS feed

Adding The Pragmatic Engineer from its RSS feed and prepopulating its name, album, and artist

Find actions and update configuration

Filtering AgentP's command palette and navigating its configuration screen

Screenshots

Podcast library Episode selection
AgentP podcast library Selecting episodes from Committing High Reason
Command palette Configuration
AgentP command palette filtered to folder actions AgentP configuration screen

Keyboard reference

Every screen lists its own keys in the bar at the bottom. Press ? to expand it, or Ctrl+K to search every action by name.

Global

Key Action
Ctrl+K Toggle the command palette
Ctrl+C Quit from anywhere, including during a download (asks first if the podcast editor has unsaved changes)
q Quit when not typing in a text field; ignored while a download is running
Ctrl+V Paste into the active text field or the palette filter
? or . Expand or collapse the key-hint bar

Any list

Available on the podcast list, episode select, podcast picker, config menu, and the podcast editor.

Key Action
Home / g Jump to the first row
End / G Jump to the last row
PageUp / PageDown Move ten rows

Podcast list

Key Action
j / ↓, k / ↑ Move selection
Enter Open episode list
Shift+↑ / Shift+↓ Reorder podcasts
r Refresh feeds
e Edit selected podcast
o Open selected podcast folder
c Config menu
D Delete selected podcast; confirm with y or D, cancel with Esc

Deleting is the one confirmation that does not take Enter. Enter opens a podcast on this screen, and removing one cannot be undone.

Episode select

Key Action
j / ↓, k / ↑ Move selection
Space Toggle episode
a Toggle all
s Sort (newest/oldest)
o Open podcast folder
Enter Download selected
Esc Back
Keys for the command palette, download screen, config menu, wizard, and editor

Command palette

Key Action
Type Filter actions
↑ / ↓, Shift+Tab / Tab Move selection
Enter Run the selected action
Esc Close

Downloading

Key Action
Esc Back to the podcast list once the run has finished
q Ignored while the transfer runs, so a stray keypress cannot leave a partial file

Config menu

The menu has nine rows: Add New Podcast, Download Folder, Default Mode, Banner Style, New Podcast Defaults, Edit Existing Podcasts, Open Config File, Open Podcasts Config File, and Open Download Folder.

Key Action
j / ↓, k / ↑ Move selection
Enter Activate the row (edit the folder path, toggle tui/cli, open an editor, or open a file or folder)
r on Download Folder Reset the download folder to the built-in default
Enter / Esc while editing the path Confirm or cancel the new folder path
y / Enter, Esc Answer a confirmation dialog
Esc Back to the podcast list

Add podcast wizard

Key Action
Enter on Feed URL Open the mode selector
1 / m Manual — fill every field yourself
2 / p / Enter Prepopulate from feed — fetches the channel title, album, and artist
Enter Next step (the last step saves the podcast)
Tab / ↓ / j on a yes/no or numeric step Next step
↑ / k / Backspace on a yes/no or numeric step Previous step
Backspace on an empty text step Previous step
Space Toggle a yes/no step
← / -, → / + Adjust the leading-zeros count
Ctrl+V Paste into a text step
Esc Cancel the wizard, or cancel an in-flight feed fetch

Edit podcast

Key Action
j / ↓, k / ↑ Move between fields
Enter Edit a text field or toggle a yes/no field
Enter / Esc while editing text Commit or cancel the edit
Space Toggle a yes/no field
← / -, → / + Adjust the leading-zeros count
r Restore the current field to its built-in default
R Reset every yes/no and numeric field to built-in defaults (template editor only)
s Save
Esc Back; asks s save / d discard / Esc cancel if there are unsaved changes
Ctrl+V Paste into the text field being edited

CLI reference

Commands that select a podcast accept either its 1-based index or a case-insensitive name. Run agentp <command> --help for the full flag list.

Podcasts

agentp podcast list
agentp podcast list --no-fetch
agentp podcast show --podcast "Darknet Diaries"
agentp podcast episodes --podcast 1 --limit 20
agentp podcast add --name "My Show" --feed-url https://example.com/feed.xml
agentp podcast add --feed-url https://example.com/feed.xml --from-feed
agentp podcast add --feed-url https://example.com/feed.xml --from-feed --artist "Jane Doe" --overwrite-file-name true
agentp podcast edit --podcast 2 --name "New Name" --feed-url https://example.com/new.xml
agentp podcast edit --podcast 2 --remove-images true
agentp podcast delete --podcast "Old Show"

New podcasts start from the default_podcast template in config.json. --from-feed fills in the name, album, and artist from the channel metadata; --name still wins if you pass both. Every per-podcast option in the table below is also a flag on podcast add and podcast edit, and yes/no flags take an explicit true or false.

Downloads

agentp download --podcast 1 --latest 5
agentp download --podcast 1 --oldest 5
agentp download --podcast 1 --episodes 3,7,12
agentp download --podcast 1 --all

--episodes, --latest, --oldest, and --all are mutually exclusive and exactly one is required. Episode index 1 is always the newest episode; agentp podcast episodes prints the indices.

Configuration and folders

agentp config show
agentp config set --download-dir ~/Podcasts
agentp config set --default-mode cli
agentp config set --banner-style ascii
agentp config path

agentp open downloads
agentp open downloads --create
agentp open podcast --podcast 1 --create

open refuses to open a folder that does not exist yet; --create makes it first.

Configuration

Config lives under $HOME/.config/AgentP/ (or %USERPROFILE%\.config\AgentP\ on Windows). agentp config path prints the directory.

  • config.json — download folder, the default_podcast template, default_mode (tui or cli), and banner_style (joined or ascii)
  • podcasts.json — your podcast list, as { "podcasts": [ ... ] }

banner_style picks the TUI banner wordmark: joined (the default) draws the letters with box-drawing characters and needs a terminal that draws those itself, such as Windows Terminal or kitty; ascii is the plain fallback for terminals that leave gaps between the strokes, Warp among them.

Per-podcast options (podcasts.json)

Each entry in podcasts.json has the same shape as default_podcast plus its identity fields. The CLI flag column applies to podcast add and podcast edit.

Field CLI flag Purpose
name --name Display name in lists
feed_url --feed-url RSS feed URL
album_name --album-name Subfolder name and album tag; falls back to name when empty
artist --artist Artist and album-artist tag
user_agent --user-agent Custom User-Agent for this podcast's audio downloads; empty uses AgentP's default
overwrite_tags --overwrite-tags Master switch for writing ID3 text tags
remove_existing_tags --remove-existing-tags Drop the source file's ID3 tag and write a fresh minimal one (only when overwrite_tags is on)
remove_images --remove-images Strip embedded cover art; works even when overwrite_tags is off
overwrite_album_name --overwrite-album-name Write the album tag
overwrite_artist --overwrite-artist Write the artist and album-artist tags
overwrite_title --overwrite-title Write the title tag
overwrite_file_name --overwrite-file-name Rename the file to the episode title
append_number_to_title --append-number-to-title Prefix the title tag with the episode number
leading_zeros_amount --leading-zeros-amount Zero-padding for that number; 3 pads to four digits (0001), 0 disables

Note

Older configs that use override_*, leading_zeros_to_title, remove_image, or create_new_tags still load. AgentP rewrites them with the current key names the next time it saves.

New-podcast defaults

The default_podcast block in config.json is copied into every podcast you create, whether through the TUI wizard or agentp podcast add. Edit it from New Podcast Defaults in the TUI config menu or directly in the file. Changing the template does not touch podcasts that already exist.

Download layout

Downloads are organized by album name, which falls back to the podcast name when empty:

<download_dir>/
└── <album_name>/
    ├── <episode>.mp3
    └── <episode>.mp3

Without overwrite_file_name, the filename is the last path segment of the episode's enclosure URL (hosts that wrap the real file URL inside a redirect link, such as Anchor, are unwrapped), falling back to the final response URL and then default.mp3. With it, the file is renamed to <sanitized episode title>.mp3. Downloading an episode again overwrites the existing file.

When overwrite_tags is on, AgentP writes the title, album, and artist plus album-artist frames that you have enabled and leaves every other frame alone. Turn on remove_existing_tags to discard the source file's tag first, which helps when a host embeds large metadata blocks that confuse players.

Note

Episode indices are 1-based with 1 = newest. This applies to --episodes, --latest, --oldest, and numeric title prefixes. With leading_zeros_amount: 3, episode 1 becomes 0001, episode 10 becomes 0010, and episode 100 becomes 0100.

Troubleshooting

  • ... (internet-filter/proxy) blocked URL ... — the host answered with an HTML or text page instead of audio. This usually means a proxy or content filter intercepted the request, or the host rejected AgentP's User-Agent. Check the filter, or set user_agent on that podcast (agentp podcast edit --podcast N --user-agent "...").
  • A feed adds fine but every download fails — some hosts (Buzzsprout's CDN, for example) refuse anonymous clients. AgentP sends AgentP/<version> by default; a browser-style user_agent on the podcast usually resolves it.
  • Episode index N is out of range — indices count from the newest episode. Run agentp podcast episodes --podcast N to see the current numbering.
  • Start over — delete config.json and podcasts.json from the directory printed by agentp config path. The next launch recreates both, including the demo podcasts.

Building from source

Requires Rust 1.88+ (edition 2024). The binary lands at target/release/agentp.

git clone https://github.com/ByteMagicInc/AgentP.git
cd AgentP
cargo build --release --locked

Before opening a pull request, run what CI runs:

cargo fmt --all -- --check && cargo clippy --all-targets -- -D warnings && cargo test --all

Contributing

Issues and PRs welcome at https://github.com/ByteMagicInc/AgentP. Read CONTRIBUTING.md before you contribute and AGENTS.md for architecture details. Start commit messages with Fix, Add, Refactor, or Update so the changelog groups them correctly.

Maintainers: see the short release guide.

License

GPL-3.0-only © 2026 ByteMagic Inc.

Releases

Packages

Contributors

Languages