A local podcast management system for macOS that automatically downloads and organizes podcast episodes from RSS feeds.
- GUI Application: Easy-to-use interface for managing podcast subscriptions
- Automatic Downloads: Queue-based system that processes downloads sequentially
- RSS Feed Support: Add podcasts by pasting their RSS feed URL
- Persistent Queue: Downloads continue even after closing the app
- Retry Logic: Automatic retry of failed downloads (up to 5 attempts)
- macOS Integration: Native notifications and launchd scheduling
- Background Processing: Downloads continue in the background
- Progress Tracking: Real-time download progress and queue status
~/Documents/Katib/
├── podcasts/
│ └── [Podcast Name]/
│ └── [Podcast Name] - YYYY-MM-DD - [Episode Title].mp3
├── transcripts/
│ └── [Podcast Name]/
│ └── [Podcast Name] - YYYY-MM-DD - [Episode Title].txt
├── config/
│ └── katib_config.json
└── logs/
└── katib_downloader_YYYY-MM-DD.log
- macOS (tested on macOS 10.14+)
- Python 3.9 or higher
- pip (Python package manager)
cd ~/Katib
pip3 install -r requirements.txtOr if you prefer using a virtual environment:
cd ~/Katib
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtTest the downloader script:
python3 katib_downloader.py --helppython3 katib.pyOr make it executable and run directly:
chmod +x katib.py
./katib.py- Launch the GUI application:
python3 katib.py - Paste the RSS feed URL in the "RSS Feed URL" field
- Click "Add Podcast"
- The system will:
- Parse the RSS feed to get the podcast name
- Queue all available episodes for download
- If there are 100+ episodes, you'll be asked to confirm
- Download Now: Click to process the download queue immediately
- Check for New Episodes: Manually check RSS feeds for new episodes
- The queue processes downloads sequentially (one at a time)
- Remove Podcast: Select a podcast from the list and click "Remove Selected"
- Note: This removes the subscription but does NOT delete downloaded files
- View Queue Status: The status panel shows pending, downloading, completed, and failed downloads
- Retry Failed Downloads: Select a failed download and click "Retry Selected"
Set up automatic daily downloads at 9 AM PT:
- Copy the launchd plist files to
~/Library/LaunchAgents/:
cp com.katib.download.plist ~/Library/LaunchAgents/
cp com.katib.transcribe.plist ~/Library/LaunchAgents/- Important: Edit the plist files to update the paths:
# Edit the plist files to use your actual home directory path
nano ~/Library/LaunchAgents/com.katib.download.plist
# Replace /Users/codyaustin with your actual username- Load the launchd agents:
launchctl load ~/Library/LaunchAgents/com.katib.download.plist
launchctl load ~/Library/LaunchAgents/com.katib.transcribe.plist- Verify they're loaded:
launchctl list | grep katib- To unload (disable automation):
launchctl unload ~/Library/LaunchAgents/com.katib.download.plist
launchctl unload ~/Library/LaunchAgents/com.katib.transcribe.plistThe downloader can also be run from the command line:
# Check all RSS feeds for new episodes
python3 katib_downloader.py --check-new
# Process the download queue
python3 katib_downloader.py --process-queue
# Do both (check new and process queue)
python3 katib_downloader.py --allConfiguration is stored in ~/Documents/Katib/config/katib_config.json. This file contains:
- podcasts: List of subscribed podcasts with metadata
- download_queue: Episodes waiting to be downloaded
- failed_downloads: Episodes that failed after 5 retry attempts
- last_check: Timestamp of last RSS feed check
You can edit this file manually if needed, but it's recommended to use the GUI.
Episodes are saved with the format:
[Podcast Name] - YYYY-MM-DD - [Episode Title].mp3
- Uses the episode's published date
- Special characters are removed from filenames
- Filenames are limited to 200 characters
- Check the queue status in the GUI
- Verify you have internet connectivity
- Check the logs in
~/Documents/Katib/logs/
- Verify the RSS URL is correct and accessible
- Some podcasts may have non-standard RSS formats
- Check the logs for specific error messages
- The system checks available disk space before downloading
- Free up space if downloads are failing
- Downloaded files are in
~/Documents/Katib/podcasts/
- Check if the plist files are in
~/Library/LaunchAgents/ - Verify the paths in the plist files are correct
- Check launchd logs:
tail -f ~/Documents/Katib/logs/launchd_download.log
Make sure the scripts are executable:
chmod +x katib.py katib_downloader.py katib_daily_download.sh katib_daily_transcribe.shLogs are stored in ~/Documents/Katib/logs/:
katib_downloader_YYYY-MM-DD.log- Daily download logslaunchd_download.log- Launchd output for download automationlaunchd_transcribe.log- Launchd output for transcription automation
- Transcription Integration: Automatic transcription using MacWhisper (placeholder ready)
- Search/Filter: Search and filter podcasts and episodes
- Pause/Resume: Pause and resume downloads
- Download Speed Limits: Configure maximum download speed
- Episode Management: Delete episodes, mark as listened, etc.
- feedparser: RSS feed parsing
- requests: HTTP downloads with streaming support
- python-dateutil: Date parsing for various RSS formats
- tkinter: GUI framework (included with Python)
- Downloads are processed sequentially (one at a time)
- Large files are streamed (not loaded entirely into memory)
- Partial downloads can be resumed
- Network errors trigger automatic retries (up to 5 attempts)
- Failed downloads after 5 retries are moved to the failed list
- Queue persists across app restarts
- Queue state is saved after each download
- Stuck downloads (status: downloading) are reset to pending on app launch
- Queue processing continues in background threads
Critical Bug Fix: Duplicate Episode Detection
- Issue: The
check_new_episodes()function was not checkingdownload_historywhen determining if episodes were already downloaded. This caused episodes to be re-added to the queue even after successful downloads, especially after the queue was cleaned of completed items. - Fix: Enhanced
check_new_episodes()to checkdownload_historyin addition to the queue and failed downloads. Now matches episodes byepisode_id,episode_url, andepisode_titleto catch duplicates even if some fields differ. - Impact: Prevents duplicate episodes from being added to the download queue. Episodes that have already been downloaded (recorded in history) will no longer appear as "new" when checking RSS feeds.
New Features:
- Clean Duplicates Button: Added automatic cleanup on startup and a manual "Clean Duplicates" button to remove queue items that are already in download history.
- Clear Queue Button: Added ability to clear all items from the download queue with confirmation dialog.
- View Queue Details: Added detailed queue viewer window showing all pending, downloading, and failed items organized by status.
- Enhanced Queue Display: Increased visibility of pending items (now shows up to 20 instead of 5) in the main status panel.
Performance Improvements:
- Optimized Podcast List Selection: Added display cache to prevent unnecessary listbox refreshes. The podcast list now only updates when data actually changes, preserving user selection and scroll position.
- Improved Refresh Logic: Periodic refreshes (every 30 seconds) now skip updates when no data has changed, reducing UI lag.
UI Improvements:
- Larger Default Window: Increased default window size from 900x700 to 1200x800 for better visibility and usability.
- Better Queue Status Display: Enhanced queue status to show more pending items and indicate when there are more items available.
Technical Changes:
- Enhanced
download_historyentries to includeepisode_idandepisode_urlfor better duplicate detection. - Added
cleanup_duplicate_queue_items()function inkatib_downloader.py. - Added
cleanup_duplicates(),clear_queue(), andshow_queue_details()methods inkatib.py. - Added display caching mechanism to reduce unnecessary UI updates.
For Future Agents:
- The duplicate detection now relies on three matching criteria: episode_id, episode_url, and episode_title. All three are checked against download_history, queue, and failed_downloads.
- The cleanup functions are safe to run - they only remove items from the queue, never delete downloaded files or history.
- The display cache (
podcasts_display_cache) prevents unnecessary listbox refreshes. If you modify the podcast list display format, remember to invalidate this cache or update the comparison logic.
This project is provided as-is for personal use.
For issues or questions:
- Check the logs in
~/Documents/Katib/logs/ - Review the troubleshooting section above
- Check the configuration file for any issues