ytcs.sh fetches YouTube channel feeds, lets you browse them with fzf, and plays videos with mpv and yt-dlp.
fzf.Required:
mpvyt-dlp or youtube-dlfzfcurljqtimgOptional:
xmlstarletkittywmctrlxclipcopyqClone the repository and make the script executable if needed:
git clone <repo-url>
cd ytcs
chmod +x ytcs.sh
Copy the example environment file and edit it for your setup:
cp ytcs.env.example ytcs.env
Play a single video URL:
./ytcs.sh 'https://www.youtube.com/watch?v=VIDEO_ID'
Open the interactive launcher:
./ytcs.sh
Refresh all cached feeds:
./ytcs.sh --refresh
Browse grouped by channel:
./ytcs.sh --grouped
Browse in chronological order:
./ytcs.sh --time
Browse by channel:
./ytcs.sh --subscription
Import subscriptions from CSV:
./ytcs.sh --import /path/to/subscriptions.csv
Add one subscription from a YouTube URL:
./ytcs.sh --addsub 'https://www.youtube.com/@kurzgesagt'
Show CLI help:
./ytcs.sh --help
--help, -h: Show help text.--loud, -l: Print progress and diagnostic output to stderr.--cli: Enable CLI mode.--kitty: Relaunch in a dedicated kitty window using ytcs-kitty.conf.--refresh, -r: Refresh all cached feeds and rebuild grouped/time caches.--import, -i FILE: Import subscriptions from CSV.--addsub URL: Add a subscription from a handle URL or /channel/ URL.--subscription, -s: Browse by channel.--grouped, -g: Browse grouped by channel.--time, --chronological, -t, -c: Browse in reverse chronological order.If no arguments are provided, ytcs.sh opens an fzf multi-select launcher for the main actions.
The default configuration in ytcs.env.example is:
export MAX_CHANNEL_AGE=182
export MAX_GROUPED_VIDS=10
#export watchtop=4
export LOUD=0
export YTDLP_COOKIES="firefox"
export MARK_AGE="TRUE"
export GEOMETRY1="1366x768+50%+50%"
export GEOMETRY2="1366x768"
export CLIMODE=0
export YTPOT_BASEURL="youtubepot-bgutilhttp:base_url=http://127.0.0.1:8080"
export YTUBE_API_KEY=""
Important settings:
MAX_CHANNEL_AGE: Maximum channel age in days for grouped view.MAX_GROUPED_VIDS: Maximum videos shown per channel in grouped view.watchtop: Maximum concurrent workers for feed refresh and parsing.YTDLP_COOKIES: Browser profile source for yt-dlp cookies.MARK_AGE: Enable or disable age markers in lists.GEOMETRY1, GEOMETRY2: mpv window geometry options.YTPOT_BASEURL: Optional extractor args for the BGUtil POTS provider.YTUBE_API_KEY: Required for resolving handle URLs in --addsub.When selecting videos, fzf shows:
media:description from the feed entrytimg, when availableIn --kitty mode, fzf fills the terminal and the preview pane is shown below the list.
${XDG_DATA_HOME:-$HOME/.local/share}/ytcs.grouped_data.txt and time_data.txt are derived caches.--refresh refreshes channel XML feeds and rebuilds both derived caches.--time uses an existing valid time_data.txt cache and only rebuilds it when the cache is missing or invalid.--addsub clears grouped/time caches so they rebuild on next use.xclip and/or copyq when available.--addsub uses the YouTube Data API for handle URLs. If YTUBE_API_KEY is not set, the script points to TunePocket’s channel ID finder:
https://www.tunepocket.com/youtube-channel-id-finder/#channle-id-finder-formMIT