Podcasts in any terminal. Fast, clean, offline.
Table of Contents
Why podliner?
- Keyboard-first & mouse-friendly. Full mouse support (click, select, scroll) with fast TUI feedback.
- Vim keys & commands. Familiar navigation (
j/k, gg/G, / to search) plus concise colon-commands (:add , :queue add, :opml import, :opml export).
- Chapters. Podcast-2.0 `` JSON and ID3 CHAP frames, with a dedicated Chapters tab and
,/. keys to jump.
- Sync progress and subscriptions via the gPodder API (gpodder.net + Nextcloud gPodder-Sync, auto-detected).
- MPRIS on Linux. Media keys (play/pause/next/prev) and status from
playerctl, KDE/GNOME widgets, etc.
- Offline-ready. Download episodes, resume where you left off, manage a queue.
- Sleep timer.
:sleep 30m / :sleep 1h30m to stop playback after a duration.
- Per-feed settings. Speed override (
:feed speed 1.5) and auto-download (:feed auto-download on) per subscription.
- Undo for destructive actions like queue clear.
- Easy migration. OPML import/export to move subscriptions between players.
- Cross-platform. Single-file builds for Linux, macOS, and Windows.
- Engine choice. Works with mpv, ffplay (FFmpeg), or VLC where available.
> No telemetry. Config lives in your user profile. All local.
Screenshots
Install (stable releases)
Linux
bash <(curl -fsSL https://github.com/timkicker/podliner/releases/latest/download/install.sh)
Or via the AUR: yay -S podliner-bin
macOS
bash <(curl -fsSL https://github.com/timkicker/podliner/releases/latest/download/install-macos.sh)
Windows (Powershell)
Via winget:
winget install --id=TimKicker.Podliner -e
Via installer:
irm https://github.com/timkicker/podliner/releases/latest/download/install.ps1 | iex
> Looking for system-wide install, uninstall, pruning, or checksum verification? See the FAQ.
Migrate from other players (OPML)
Most podcast players support OPML export/import.
- Export your subscriptions from the old player as an
.opml file (e.g. subscriptions.opml).
- In podliner, run
:opml import to import.
- To export your current subscriptions from podliner, run
:opml export. With no path, it writes to your Documents folder as:
- Linux/macOS:
~/Documents/podliner-feeds.opml
- Windows:
%USERPROFILE%\Documents\podliner-feeds.opml
- If you prefer to drop files in place, podliner stores its config here:
- Linux/macOS:
${XDG_CONFIG_HOME}/podliner or ~/.config/podliner
- Windows:
%APPDATA%\podliner
gPodder sync
Podliner syncs your subscriptions and play history with any gPodder-compatible server. Two protocol flavors are supported and auto-detected at login:
- gpodder.net (public) + self-hosted gpodder API v2 servers (mygpo, opodsync, podfetch…).
- Nextcloud with the gPodder-Sync app.
Quick start
# gpodder.net
:sync login https://gpodder.net
# Nextcloud (plain username/password works; see 2FA note below)
:sync login https://cloud.example.com
:sync ← pull + push (full sync)
:sync auto on ← sync automatically on startup and exit
Nextcloud + 2FA / WebAuthn: generic Basic-Auth with your normal password fails with HTTP 401 on 2FA-enabled accounts. Create a dedicated App-Password in Nextcloud (Settings → Security → Devices & sessions → Create new app password) and use that.
The detected flavor is stored in gpodder.json so subsequent launches don't re-probe. :sync status shows which flavor is active. Run :sync help in the app for the full command reference.
Credentials are stored in the OS keyring when available (libsecret on Linux, Keychain on macOS, Credential Store on Windows), with a plaintext fallback in gpodder.json if the keyring is unavailable.
Commands (essentials)
> Full help browser: :h | Full list: see COMMANDS
Playback
- Enter: play selected
- Space: pause/resume
- Left/Right: seek 10s backward/forward
[ / ]: slower / faster
, / .: previous / next chapter (if available)
:sleep 30m | :sleep 1h30m | :sleep off: sleep timer
Navigation & filters
- j / k: move down / up
- h / l: walk the panes left / right (feeds → episodes → shownotes → chapters)
- g / G: jump to the start / end of the episode
- / : search in current list •
Esc: leave the search
- u : toggle "unplayed only"
i: open Shownotes tab • Esc: back to episodes
Chapters
- Dedicated Chapters tab next to Episodes/Details; shows
Chapters (N) with a count. Reach it with l from the shownotes tab
, / .: jump to previous / next chapter globally
- Enter on a chapter row: seek to that chapter
:chapter list|next|prev|jump : explicit commands
- Chapters come from Podcast-2.0 `` URLs and ID3 CHAP frames (local file or HTTP Range)
Downloads & queue
- d : download or show status
:download rm (alias :dl rm) : delete the downloaded file and free the space
- :feed queue : switch to queue view
- :queue add|toggle|rm|clear|shuffle : queue ops for selected episode
- :play-next / :play-prev : next/previous in queue
:undo : revert the last destructive action (:queue clear, :queue rm)
Feeds
:add : add feed
:refresh : fetch every feed now. Feeds are also fetched on their own after start and every 60 minutes; :refresh auto or :refresh auto off changes that, and the sidebar title shows how old they are
:feed all|saved|downloaded|history|queue : switch view
:feed speed : per-feed playback speed override (e.g. :feed speed 1.5)
:feed auto-download on|off : auto-queue new episodes from this feed for download
Misc
- t : toggle theme
- q : quit
- :w / :wq : save / save & quit
Configuration & data
- Config:
- Linux:
$XDG_CONFIG_HOME/podliner/ (fallback: ~/.config/podliner/)
- macOS:
$XDG_CONFIG_HOME/podliner/ (fallback: ~/.config/podliner/)
- Windows:
%APPDATA%\podliner\
- Logs:
- Linux:
$XDG_STATE_HOME/podliner/logs/ (fallback: ~/.local/state/podliner/logs/)
- Windows:
%LOCALAPPDATA%\podliner\logs\
- File pattern:
podliner-.log (daily)
- Example:
…/podliner/logs/podliner-YYYYMMDD.log
- Feed refresh: every 60 minutes by default, set with
:refresh auto or RefreshIntervalMinutes in appsettings.json (0 turns it off, otherwise 5 minutes to a week). --offline fetches nothing.
- Downloads:
~/Podcasts/ by default (all platforms). Override at runtime with :downloads set-dir (or set-dir reset to restore default), or by setting DownloadDir in appsettings.json.
- OPML: imports/exports under Migrate from other players (OPML)
> Back up appsettings.json and library.json to migrate settings and library to another machine.
Audio engines
podliner can use different players:
- VLC (via LibVLC; bundled on Windows via
VideoLAN.LibVLC.Windows, install vlc on Linux/macOS). Preferred: full seek/speed/volume support.
- mpv (IPC socket). Full feature support.
- Media Foundation (Windows only, built-in). No playback speed control.
- builtin (in podliner, nothing to install). Seek, speed and volume; mp3 only. The fallback on macOS, on other systems only with
:engine builtin.
- ffplay (part of ffmpeg). Fallback only: coarse seek by restart, no live speed/volume.
Install examples:
- Debian/Ubuntu:
sudo apt-get install -y vlc mpv ffmpeg
- Fedora:
sudo dnf install -y vlc mpv ffmpeg
- Arch:
sudo pacman -S --needed vlc mpv ffmpeg
- macOS:
brew install --cask vlc && brew install mpv ffmpeg
- Windows: VLC is bundled;
mpv/ffmpeg optional via your package manager of choice.
Engine selection & fallback:
- Default is
auto: tries VLC first, then an OS-specific fallback chain (Windows: MediaFoundation → mpv → ffplay; macOS: mpv → builtin → ffplay; Linux: mpv → ffplay).
- Switch engines at runtime with
:engine vlc|mpv|ffplay|mediafoundation|builtin.
:play-source auto|local|remote controls whether to prefer local downloads or the remote URL.
FAQ / Troubleshooting
"No audio engine found”
Boxes instead of symbols (Windows console)
The Windows console does not carry every glyph podliner uses, so the clock, queue and pause symbols can come out as boxes. Start it with --ascii to switch the whole UI to plain characters.
"podliner needs a console to draw on"
podliner draws a full-screen interface and cannot do that when its output is piped or redirected. Run it from a terminal. --version and --help work without one.
System-wide install?
- Linux/macOS: add
--system to the install command.
- Windows (PowerShell): run
Install-Podliner -System after the bootstrap line.
Update / Uninstall / Prune
- Update to latest stable: re-run the install command for your OS.
- Uninstall (Linux):
bash <(curl -fsSL https://github.com/timkicker/podliner/releases/latest/download/install.sh) --uninstall
- Uninstall (macOS):
bash <(curl -fsSL https://github.com/timkicker/podliner/releases/latest/download/install-macos.sh) --uninstall
- Uninstall (Windows, PowerShell):
irm https://github.com/timkicker/podliner/releases/latest/download/install.ps1 | iex
Uninstall-Podliner
- Prune old versions (keep active): use
--prune on Linux/macOS or Prune-Podliner on Windows.
Verify checksums
# Download checksums (stable)
curl -fsSLO https://github.com/timkicker/podliner/releases/latest/download/SHA256SUMS
# Example: verify Linux x64 tarball
curl -fsSLO https://github.com/timkicker/podliner/releases/latest/download/podliner-linux-x64.tar.gz
grep 'podliner-linux-x64.tar.gz$' SHA256SUMS | sha256sum -c -
podliner: command not found
Add install path to PATH:
- Linux:
export PATH="$HOME/.local/bin:$PATH" (in ~/.bashrc / ~/.zshrc)
- macOS:
export PATH="$HOME/bin:$PATH" (in ~/.zprofile / ~/.zshrc)
- Windows: ensure
%LOCALAPPDATA%\Microsoft\WindowsApps is on PATH
Reset config
Quit, then move the config directory away (see Configuration & data), restart to re-initialize.
Contributing
I welcome all focused PRs.
Please take a look at ROADMAP.md
Local dev:
dotnet build
dotnet run --project Podliner.App
Guidelines (short):
- C# with
nullable enabled; keep logging via Serilog.
- Prioritize robustness and UX over features.
PR flow:
- Fork → branch → PR to
main
Bug reports, logs & roadmap
When filing an issue, please include:
podliner --version output (shows exact version + RID)
- OS + architecture (e.g.,
linux-x64, osx-arm64, win-x64)
- Steps to reproduce (short and precise)
- Logs: attach the most recent file from
logs/ next to the binary (pattern podliner-*.log)
Example: …/podliner/logs/podliner-20250101.log
Security-sensitive issues: contact tim@kicker.dev.
License and credits
Libraries used
Engines and tools
- VLC - media engine (via LibVLC)
- mpv - media engine (optional)
- FFmpeg / ffplay - tools and fallback playback