podpull

A fast, minimal CLI tool for downloading and synchronizing podcasts from RSS feeds. No cloud services, no accounts, no databases — just your podcasts, stored locally, under your control.

No Database, No Config

The output directory IS the state. No hidden files, no databases. Just look at your folder to see what you have.

Smart Sync

Only downloads what's missing. Episodes identified by GUID — run it repeatedly and only new episodes are fetched.

Fast & Concurrent

Parallel downloads with configurable concurrency. Atomic writes with SHA-256 integrity verification.

Terminal

Quick Start

cargo install podpull

Available on crates.io

Download pre-built binaries from GitHub Releases:

View Releases
git clone https://github.com/jakobwesthoff/podpull.git
cd podpull
cargo build --release

Basic Usage

# Download a podcast
podpull https://example.com/podcast/feed.xml ~/Podcasts/my-show/

# Sync new episodes (already downloaded ones are skipped)
podpull https://example.com/podcast/feed.xml ~/Podcasts/my-show/

# Download faster with more connections
podpull -c 5 https://feeds.example.com/podcast.xml ~/Podcasts/my-show/

# Gradually download a large back-catalog
podpull -l 10 https://feeds.example.com/podcast.xml ~/Podcasts/my-show/

Documentation

CLI Options

Option Default Description
<feed> Required RSS feed URL or path to local file
<output-dir> Required Directory for downloaded episodes
-c, --concurrent <N> 3 Maximum concurrent downloads
-l, --limit <N> Only download the N most recent undownloaded episodes
-q, --quiet Suppress progress output
-h, --help Print help
-V, --version Print version

Output Structure

Each podcast gets its own directory containing the audio files and metadata:

~/Podcasts/my-show/
├── podcast.json                      # Feed metadata
├── 2024-01-15-episode-title.mp3      # Audio file
├── 2024-01-15-episode-title.json     # Episode metadata
├── 2024-01-08-another-episode.mp3
└── 2024-01-08-another-episode.json

Metadata Format

Feed-level metadata in podcast.json:

{
  "title": "My Favorite Podcast",
  "description": "A podcast about interesting things",
  "author": "Podcast Author",
  "link": "https://example.com/podcast",
  "feed_url": "https://example.com/podcast/feed.xml",
  "last_synced": "2024-01-15T10:30:00Z"
}

Episode metadata alongside each audio file:

{
  "guid": "episode-unique-id-123",
  "title": "Episode Title",
  "published": "2024-01-15T08:00:00Z",
  "url": "https://example.com/episode.mp3",
  "content_hash": "sha256:abc123...",
  "downloaded_at": "2024-01-15T10:30:00Z"
}