My podcatcher is a Python script
Sometimes, an app can be a home-cooked meal. This is a story of one of those times.
I like to binge “actual play RPG” podcasts in the background while I work. Finding a decent desktop-oriented podcatcher app in 2025 is surprisingly difficult, since most target mobile. I’ve tried Podgrab and PodFetch, but neither fit my binge pattern: I want to listen to episodes in chronological order, typically starting a few years into the back catalog. The upshot of this is that each time I continue listening, I have to scroll through 6 pages of back episodes to find where I left off; then after each episode I have to manually skip backwards to the “previous” episode (since these apps say that the “next” episode is the next older episode, not the next newer one).
Realizing that podcasts are just RSS streams with mp3 files, I decided to try something crazy: what if I built my own podcatcher that simply downloads MP3 files and opens them in VLC? It turns out I could, and the interface ended up being even better than I’d imagined.
How it works
Section titled “How it works”The “app” consists of a few parts:
- VLC to play the episodes. VLC supports “resume playback”, so I can pick up right where I left off.
- A Markdown playlist / database. This stores which episodes I’ve already listened to and the next ones in the sequence.
- A Python script that glues it together.
The Python script is a CLI tool named @podcast
. It has two key functions: updating the playlist with the latest episodes, and downloading the MP3 for the next episode in sequence. You can download the @podcast script here if you are interested.
The “database” is just a Markdown file. Using a Markdown file as a database is probably the coolest part of this project—it’s a human-readable format that can be edited in a WYSIWYG text editor, giving you a nice “database administration interface” for free. It looks like this:
Podcasts
Section titled “Podcasts”Completed series:
- Naddpod C1 (Bahumia)
- Critical Role S2
- Fun City (Podcast Index) - Float City, Cozy City, Precious Cargo, Fun City (up to 53)
Current series
Section titled “Current series”Episode list: RSS
The part at the top is just for my reference, when I’m looking for what series to dive into next. The “Current series” section has a link to the episode list, which the Python script uses to sync the playlist part. The rest is the playlist, which is a Markdown TODO list for each episode.
Updating the episode list
Section titled “Updating the episode list”When I run @podcast update-episodes
, it scans the Markdown database for the “Episode list” link and extracts the URL. It then downloads that RSS feed, parses the metadata for each episode, and appends any new episodes as unwatched items to the end of the Markdown file.
Getting the next episode
Section titled “Getting the next episode”When I run @podcast download
, it scans the Markdown database for the first incomplete item in the TODO list and extracts the URL. Then it downloads that URL and updates the Markdown file to mark that item as complete.
I download the file using curl instead of Python’s libraries. This gives me curl’s progress reporting and resume support without any extra work.
Conclusion
Section titled “Conclusion”This workflow thrives because of several small features of other apps working together. When I want to listen to the next episode, I can just type F3, @podc
, right arrow, enter. How?
- I have the iTerm2 hotkey window (“Quake terminal”) set up on F3, which opens a terminal from any other app.
- I have
@podcast
in my PATH, so I can run it from any directory. - I use fish shell, which identifies
@podcast download
as my most recent command that started with@podc
, allowing me to just hit right arrow and enter to execute it.
This podcatcher app took me about 3 hours to build, and I’ve been using it virtually unchanged for over a year now. It’s a perfect example of how a home-cooked app can be exactly what you need, even when it’s dead simple.