The only PodcastIndex tool that is agent-native and works offline: search, resolve, and analyse any podcast from one signed binary with a local mirror you can FTS and SQL.
Every existing PodcastIndex tool is a language SDK that mirrors the endpoints and returns raw JSON in-process. This CLI adds a local SQLite mirror, full-text search over synced shows and episodes, agent-native output, and compound commands no wrapper has: tgrep searches inside transcripts, cadence and dead-watch reason over publish history, guest-graph joins people across feeds.
Learn more at PodcastIndex.
Created by @adbonnet.
Authentication
PodcastIndex signs every request with four headers: X-Auth-Key, X-Auth-Date (unix now), Authorization (sha1 of key+secret+date), and User-Agent. Set PODCASTINDEX_KEY and PODCASTINDEX_SECRET and the CLI computes the signature for you on each call.
Quick Start
# verify the signer and credentials without hitting the API
podcastindex-pp-cli doctor --dry-run
# search podcasts by term
podcastindex-pp-cli find search-byterm --q "batman university" --max 5
# find episodes featuring a person
podcastindex-pp-cli find search-byperson --q "adam curry" --max 5
# resolve a show to its recent episodes
podcastindex-pp-cli episodes byfeedid --id 75075 --newest --max 10
Unique Features
These capabilities aren't available in any other tool for this API.
Mine data wrappers ignore
-
tgrep — Search inside actual episode transcripts, not just titles and descriptions.
Reach for this when the user wants what was said in episodes, not show metadata.
podcastindex-pp-cli tgrep "jepa" --cat Technology --agent
Recipes
Resolve a show in one step
podcastindex-pp-cli find search-byterm --q "no agenda" --max 1 --json --select feeds.id,feeds.title
Get the feedId for a show by name, ready to pass to episodes byfeedid.
Find a person's (or company's) appearances
This is the primary path for "where did X appear". PodcastIndex has no
episode-content or guest search — find search-byterm matches feed metadata,
find search-byperson matches <podcast:person> tags (and fuzzy-matches the
first name, so it is noisy and misses untagged guests). So you cannot reach an
untagged appearance from a name alone: find the show first (a web search),
then resolve it here.
# A guest on a known show — resolves the show, filters its episodes by name,
# emits the enclosure URLs ready to transcribe.
podcastindex-pp-cli workflow find-appearances --match "Arthur Mensch" --show "Big Technology" \
--json --select feedTitle,title,datePublished,enclosureUrl
# Company + founder across a candidate show
podcastindex-pp-cli workflow find-appearances --match "Implicity" --match "Arnaud Rosier" \
--show "Med in Tech"
# Scan an explicit feed id directly (skip the show lookup)
podcastindex-pp-cli workflow find-appearances --match "Rosier" --feed 4712435
--match is repeatable (OR-matched against each episode's title and
description); --show and --feed are repeatable. Add --byperson to also fold
in tag-based hits (still filtered through --match). Prefer this over
find search-byperson whenever you know the show.
Catch up on a show
podcastindex-pp-cli episodes byfeedid --id 920666 --newest --max 10 --json --select items.title,items.datePublished,items.enclosureUrl
List a show's newest episodes with just the fields an agent needs.
Search inside transcripts
podcastindex-pp-cli tgrep "interest rates" --cat Business --agent
Full-text search the actual transcript files, not just show metadata.
Usage
Run podcastindex-pp-cli --help for the full command reference and flag list.
Commands
categories
Categories used by the Podcast Index
podcastindex-pp-cli categories - Return all the possible categories supported by the index.
Example: https://api.podcastindex.org/api/1.0/categories/list?pretty
episodes
Find details about one or more episodes of a podcast or podcasts.
podcastindex-pp-cli episodes byfeedid - This call returns all the episodes we know about for this feed from the PodcastIndex ID.
Episodes are in reverse chronological order.
When using the enclosure parameter, only the episode matching the URL is returned.
Examples:
Examples:
The feedid, feedurl, or podcastguid is required.
Examples:
Example: https://api.podcastindex.org/api/1.0/episodes/byid?id=16795090&pretty
podcastindex-pp-cli episodes byitunesid - This call returns all the episodes we know about for this feed from the iTunes ID.
Episodes are in reverse chronological order.
When using the enclosure parameter, only the episode matching the URL is returned.
Examples:
Example: https://api.podcastindex.org/api/1.0/episodes/bypodcastguid?guid=856cd618-7f34-57ea-9b84-3600f1f65e7f&pretty
podcastindex-pp-cli episodes live - Get all episodes that have been found in the podcast:liveitem from the feeds.
Examples:
Examples:
find
Manage find
podcastindex-pp-cli find search - Replaces the Apple search API but returns data from the Podcast Index database.
Note: No API key needed for this endpoint.
Example:
It searches the following fields:
- Person tags
- Episode title
- Episode description
- Feed owner
- Feed author
Examples:
Example: https://api.podcastindex.org/api/1.0/search/byterm?q=batman+university&pretty
podcastindex-pp-cli find search-bytitle - This call returns all of the feeds where the title of the feed matches the search term (ignores case).
Example "everything everywhere daily" will match the podcast
Everything Everywhere Daily by "everything everywhere" will not.
Example: https://api.podcastindex.org/api/1.0/search/bytitle?q=everything+everywhere+daily&pretty
podcastindex-pp-cli find search-music-byterm - This call returns all of the feeds that match the search terms in the title, author or owner of the
where the medium is music.
Example: https://api.podcastindex.org/api/1.0/search/music/byterm?q=able+kirby&pretty
lookup
Manage lookup
podcastindex-pp-cli lookup - Replaces the Apple podcast lookup API but returns data from the Podcast Index database.
Note: No API key needed for this endpoint.
Example:
podcasts
Find details about a Podcast and its feed.
podcastindex-pp-cli podcasts batch-byguid - This call returns everything we know about the feed from the feed's GUID provided in JSON array in the body of the request.
The GUID is a unique, global identifier for the podcast. See the namespace spec for
guid for details.
podcastindex-pp-cli podcasts byfeedid - This call returns everything we know about the feed from the PodcastIndex ID
Examples:
Examples:
The GUID is a unique, global identifier for the podcast. See the namespace spec for
guid for details.
Examples:
Example: https://api.podcastindex.org/api/1.0/podcasts/byitunesid?id=1441923632&pretty
podcastindex-pp-cli podcasts bymedium - This call returns all feeds marked with the specified
medium tag value.
Example: https://api.podcastindex.org/api/1.0/podcasts/bymedium?medium=music&pretty
podcastindex-pp-cli podcasts bytag - This call returns all feeds that support the specified
podcast namespace tag.
The only supported tags are:
podcast:value using the podcast-value parameter
podcast:valueTimeSplit using the podcast-valueTimeSplit parameter
Only the podcast-value or podcast-valueTimeSplit parameter should be used. If multiple are specified, the
first parameter is used and the others are ignored.
When called without a start_at value, the top 500 feeds sorted by popularity are returned in descending order.
When called with a start_at value, the feeds are returned sorted by the feedId starting with the specified value
up to the max number of feeds to return. The nextStartAt specifies the value to pass to the next start_at.
Repeat this sequence until no items are returned.
Examples:
Hourly statistics can also be access at https://public.podcastindex.org/podcastindex_dead_feeds.csv
For details, see Dead Feeds.
Example: https://api.podcastindex.org/api/1.0/podcasts/dead?pretty
podcastindex-pp-cli podcasts trending - This call returns the podcasts/feeds that in the index that are trending.
Example: https://api.podcastindex.org/api/1.0/podcasts/trending?pretty
recent
Find recent additions to the index
podcastindex-pp-cli recent data - This call returns every new feed and episode added to the index over the past 24 hours in reverse chronological order.
This is similar to /recent/feeds but uses the date the feed was found by the index rather than the feed's
internal timestamp.
Similar data can also be accessed using object storage root url https://tracking.podcastindex.org/current
For details, see Current.
Examples:
Example: https://api.podcastindex.org/api/1.0/recent/episodes?max=7&pretty
podcastindex-pp-cli recent feeds - This call returns the most recent max feeds, in reverse chronological order.
Examples:
Examples:
Example: https://api.podcastindex.org/api/1.0/recent/newvaluefeeds?pretty
podcastindex-pp-cli recent soundbites - This call returns the most recent max soundbites that the index has discovered.
A soundbite consists of an enclosure url, a start time and a duration.
It is documented in the podcast namespace.
Example: https://api.podcastindex.org/api/1.0/recent/soundbites?pretty
stats
Statistics for items in the Podcast Index
podcastindex-pp-cli stats - Return the most recent index statistics.
Hourly statistics can also be access at https://stats.podcastindex.org/hourly_counts.json
For details, see Stats Hourly Counts.
Daily statistics can also be access at https://stats.podcastindex.org/daily_counts.json.
For details, see Stats Daily Counts.
Example: https://api.podcastindex.org/api/1.0/stats/current?pretty
value
The podcast's "Value for Value" information
podcastindex-pp-cli value batch-byepisodeguid - This call returns the information for supporting the podcast episode via one of the "Value for Value" methods from
a JSON object containing one or more podcast GUID and one or more episode GUID for the podcast.
The JSON object key shall be the podcastguid from the podcast:guid tag in the feed.
This value is a unique, global identifier for the podcast. See the namespace spec for
guid for details.
The value of the podcastguid shall be an array of episodeguid values.
This is the unique guid specified for the <item> in the feed but may not be globally unique.
Note: No API key needed for this endpoint.
podcastindex-pp-cli value byepisodeguid - This call returns the information for supporting the podcast episode via one of the "Value for Value" methods from
podcast GUID and the episode GUID.
The podcastguid is the GUID from the podcast:guid tag in the feed. This value is a unique, global identifier
for the podcast. See the namespace spec for
guid for details.
The episodeguid is the unique guid specified for the <item> in the feed but may not be globally unique.
Note: No API key needed for this endpoint.
Examples:
Additionally, the value block data can be accessed using static JSON files (updated every 15 minutes).
Note: No API key needed for this endpoint.
Examples:
Additionally, the value block data can be accessed using static JSON files (updated every 15 minutes).
Note: No API key needed for this endpoint.
Examples:
Note: No API key needed for this endpoint.
Example: https://api.podcastindex.org/api/1.0/value/bypodcastguid?guid=917393e3-1b1e-5cef-ace4-edaa54e1f810&pretty
Output Formats
# Human-readable table (default in terminal, JSON when piped)
podcastindex-pp-cli categories
# JSON for scripting and agents
podcastindex-pp-cli categories --json
# Filter to specific fields
podcastindex-pp-cli categories --json --select id,name,status
# Dry run — show the request without sending
podcastindex-pp-cli categories --dry-run
# Agent mode — JSON + compact + no prompts in one flag
podcastindex-pp-cli categories --agent
Agent Usage
This CLI is designed for AI agent consumption:
- Non-interactive - never prompts, every input is a flag
- Pipeable -
--json output to stdout, errors to stderr
- Filterable -
--select id,name returns only fields you need
- Previewable -
--dry-run shows the request without sending
- Explicit retries - add
--idempotent to create retries when a no-op success is acceptable
- Confirmable -
--yes for explicit confirmation of destructive actions
- Piped input - write commands can accept structured input when their help lists
--stdin
- Offline-friendly - sync/search commands can use the local SQLite store when available
- Agent-safe by default - no colors or formatting unless
--human-friendly is set
Exit codes: 0 success, 2 usage error, 3 not found, 4 auth error, 5 API error, 7 rate limited, 10 config error.
Health Check
podcastindex-pp-cli doctor
Verifies configuration, credentials, and connectivity to the API.
Configuration
Config file: ~/.config/podcastindex-org-pp-cli/config.toml
Static request headers can be configured under headers; per-command header overrides take precedence.
Environment variables:
| Name | Kind | Required | Description |
|---|
PODCASTINDEX_KEY | per_call | No | Set to your API credential. |
PODCASTINDEX_ORG_API_KEY | per_call | No | Set to your API credential. |
agentcookie (optional)
If you use agentcookie to sync secrets across machines, this CLI auto-adopts agentcookie-managed credentials with no extra setup. When the daemon writes to this CLI's config, podcastindex-pp-cli doctor reports agentcookie: detected and auth-status labels the source as agentcookie. Skip this section if you don't use agentcookie - the CLI works the same as any other.
Troubleshooting
Authentication errors (exit code 4)
- Run
podcastindex-pp-cli doctor to check credentials
- Verify the environment variable is set:
echo $PODCASTINDEX_KEY
Not found errors (exit code 3)
- Check the resource ID is correct
- Run the
list command to see available items
API-specific
- 401 / authorization error — ensure PODCASTINDEX_KEY and PODCASTINDEX_SECRET are exported; run doctor to check clock skew on X-Auth-Date
- empty results on a known term — drop --clean or add --fulltext; the API truncates descriptions unless --fulltext is set
Sources & Inspiration
This CLI was built by studying these projects and resources:
Generated by CLI Printing Press