https://github.com/timkicker/podliner
Podcasts in any terminal. Fast, clean, offline.
https://github.com/timkicker/podliner
cross-platform dotnet podcast tui
Last synced: about 2 months ago
JSON representation
Podcasts in any terminal. Fast, clean, offline.
- Host: GitHub
- URL: https://github.com/timkicker/podliner
- Owner: timkicker
- License: gpl-3.0
- Created: 2025-09-16T19:32:02.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2026-02-21T00:03:54.000Z (4 months ago)
- Last Synced: 2026-02-21T05:17:13.948Z (4 months ago)
- Topics: cross-platform, dotnet, podcast, tui
- Language: C#
- Homepage:
- Size: 2.15 MB
- Stars: 134
- Watchers: 0
- Forks: 5
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Security: SECURITY.md
- Roadmap: ROADMAP.md
Awesome Lists containing this project
- awesome-tuis - podliner - platform podcast client (Table of Contents)
README
Podcasts in any terminal. Fast, clean, offline.
---
## Table of Contents
- [Why podliner?](#why-podliner)
- [Screenshots](#screenshots)
- [Install (stable releases)](#install-stable-releases)
- [Quick start](#quick-start)
- [Migrate from other players (OPML)](#migrate-from-other-players-opml)
- [gPodder sync](#gpodder-sync)
- [Commands (essentials)](#commands-essentials)
- [Configuration & data](#configuration--data)
- [Audio engines](#audio-engines)
- [FAQ / Troubleshooting](#faq--troubleshooting)
- [Contributing](#contributing)
- [Bug reports, logs & roadmap](#bug-reports-logs--roadmap)
- [License & credits](#license--credits)
---
## 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
bash <(curl -fsSL https://github.com/timkicker/podliner/releases/latest/download/install.sh)
```
Or via the [AUR](https://aur.archlinux.org/packages/podliner-bin): `yay -S podliner-bin`
### macOS
```bash
bash <(curl -fsSL https://github.com/timkicker/podliner/releases/latest/download/install-macos.sh)
```
### Windows (Powershell)
Via [winget](https://winstall.app/apps/TimKicker.Podliner):
```powershell
winget install --id=TimKicker.Podliner -e
```
Via installer:
```powershell
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](#faq--troubleshooting).
## 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](https://github.com/thrillfall/nextcloud-gpodder) 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](./COMMANDS.md)
**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
- gg / G: jump to top / bottom
- / : search in current list
- 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
- `,` / `.`: 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
- :feed queue : switch to queue view
- :queue add|rm|clear|shuffle : queue ops for selected episode
- :play-next / :play-prev : next/previous in queue
- `:undo` : revert the last destructive action (e.g. `:queue clear`)
**Feeds**
- `:add ` : add feed
- `: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`
- **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)](#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.
- **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; Linux/macOS: mpv → ffplay).
- Switch engines at runtime with `:engine vlc|mpv|ffplay|mediafoundation`.
- `:play-source auto|local|remote` controls whether to prefer local downloads or the remote URL.
## FAQ / Troubleshooting
### "No audio engine found”
- Install one of: **mpv**, **ffplay** (ffmpeg), or **VLC**. See [Audio engines](#audio-engines).
### 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
bash <(curl -fsSL https://github.com/timkicker/podliner/releases/latest/download/install.sh) --uninstall
```
- Uninstall (macOS):
```bash
bash <(curl -fsSL https://github.com/timkicker/podliner/releases/latest/download/install-macos.sh) --uninstall
```
- Uninstall (Windows, PowerShell):
```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
```bash
# 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](#configuration--data)), restart to re-initialize.
## Contributing
I welcome all focused PRs.
Please take a look at [ROADMAP.md](./ROADMAP.md)
**Local dev:**
```bash
dotnet build
dotnet run --project StuiPodcast.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
- License: [GPLv3](LICENSE)
**Libraries used**
- [Terminal.Gui](https://github.com/migueldeicaza/gui.cs) - TUI framework
- [Serilog](https://serilog.net/) and [Serilog.Sinks.File](https://github.com/serilog/serilog-sinks-file) - logging
- [AngleSharp](https://anglesharp.github.io/) - HTML parsing
- [CodeHollow.FeedReader](https://github.com/codehollow/FeedReader) - RSS/Atom parsing
- [LibVLCSharp](https://github.com/videolan/libvlcsharp) - VLC bindings
- [VideoLAN.LibVLC.Windows](https://www.nuget.org/packages/VideoLAN.LibVLC.Windows) - LibVLC binaries for Windows
- [NAudio](https://github.com/naudio/NAudio) - Windows audio helpers (Media Foundation)
- [Tmds.DBus](https://github.com/tmds/Tmds.DBus) - D-Bus client (MPRIS on Linux)
**Engines and tools**
- [VLC](https://www.videolan.org/) - media engine (via LibVLC)
- [mpv](https://mpv.io/) - media engine (optional)
- [FFmpeg / ffplay](https://ffmpeg.org/) - tools and fallback playback