Skip to content

aglairdev/yt-x

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

460 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

📺 yt-x

Browse YouTube and other yt-dlp supported sites directly from your terminal or app launcher.

GitHub Issues or Pull Requests GitHub License GitHub file size in bytes GitHub Release GitHub commit activity

recording_20260509_095830.mp4
View Demos & Previews

Full Demo:

yt-x-full-github-demo.webm

Riced/Customized Previews:

image image image image image image image image image image image image image image image image image image image

Table of Contents

Features

  • Multiple Launcher Support: with fzf, rofi all supporting previews
  • Search For Media: videos, playlists, channels, shorts or movies.
  • Search Filters: Apply colon-prefixed quick filters directly to search queries:
    • Time: :hour, :today, :week, :month, :year
    • Type: :video, :movie, :live, :short, :long
    • Features: :4k, :hd, :hdr, :subtitles, :360, :vr, :3d, :local
    • Sort by: :newest, :views, :rating
  • Search History & Recall: Automatically saves search history. Allows quick recall of previous searches using bang syntax (e.g., !1 for the most recent search, !2 for the second, etc.).
  • YouTube Feeds: Access personal feeds including the Home Feed, Trending, Watch Later, Liked Videos, Watch History, and Clips.
  • Channel Browsing: access a channel's Videos, Featured content, Playlists, Shorts, Live Streams, Podcasts, and search pages.
  • Theming & Styling: theming support through .theme extensions with tokyo night as the default theme.
  • Multi-language Support: Loadable language files (.lang) to easily localize the UI prompts and messages(currently es and br. Would appreciate contributions for more languages.
  • Pagination: browse through massive lists with Next/Previous pagination controls (default is 30).
  • scriptable Shortcuts: Bypass menus and jump straight to specific feeds, searches, or actions using direct command-line flags . See usage
  • Multiple Player Support: with mpv, vlc, and tplay.
  • Playlist Actions: Play individual videos, queue/play entire playlists, or queue "Listen to All" for audio-only
  • Auto-Mix Generation: Dynamically generates .m3u8 playlist mixes based on a single video (YouTube "Mix" feature replication).
  • Background Playback: Option to disown the media player process (CONFIG_DISOWN_PLAYER)
  • Granular Downloads: Download single videos, entire playlists, or extract audio-only (MP3 format).
  • Smart Archiving: Utilizes a download archive directory(yt-dlp's --download-archive opt) to track previously downloaded media and prevent duplicate downloads.
  • Organized File Structure: Automatically routes downloads into structured directories (e.g., video/individual/ChannelName/ or audio/PlaylistName/ChannelName/).
  • Enumeration Toggle: Easily toggle file prefix enumeration (01 -, 02 -) to keep downloaded playlist items in order.
  • Local Subscriptions Sync: Syncs your actual YouTube subscriptions locally by passing browser cookies to yt-dlp
  • Local Watch History (Recent): Automatically tracks recently watched media in a local JSON file to resume or re-watch easily.
  • Saved Videos & Playlists: Create local "Saved Videos" and "Custom Playlists for watching later without having to download them
  • Browser Cookies: optionally configure a browser (CONFIG_BROWSER passes to yt-dlp's --cookies-from-browser) to access age-restricted or account-specific content.
  • Custom Commands: Create custom cmds that execute specific URLs and yt-dlp options (e.g., setting up a command to browse a completely different streaming site that yt-dlp supports).
  • Extensions: extend yt-x with custom scripts, sites, themes, and commands placed in $HOME/.config/yt-x/extensions/.
  • Stateful Sub-Shell Execution: Drop into a shell pre-loaded with the environment variables of your current session (current video title, URL, channel info, etc.) for custom scripting
  • Desktop Integration: generate a .desktop file, to be launched natively from application menus (Linux).
  • Cache Management: Automatically cleans up stale preview images, auto-generated playlists, and logs older than a set period (Default: 7 days)
  • OS Support: Works across Linux, macOS, Windows (via WSL/MSYS/Cygwin), and Android (uses am start intents to open media natively in Android apps like VLC or MPV).
  • Auto-Updater: update checker that securely pulls the latest version from GitHub and shows you the changes diff so you can decide whether to apply the update or not.
  • Shell Completions: currently supports for fish shell with tab complete for some options (e.g., channel names, custom cmd names, etc.), would appreciate contributions for bash and zsh completions.

Installation

Linux macOS Windows Android Arch Linux NixOS

Prerequisites

Required:

  • yt-dlp - For fetching the data and downloading media.
  • fzf - Main launcher
  • jq - For parsing json
  • curl - For fetching script updates and preview images. (version 7.6+; that supports --parallel downloads)
  • sh - Any POSIX-compliant shell (Bash, Zsh, Dash, etc.).
  • Nerd Font - For the icons (Recommended JetBrains Mono Nerd Font).

Optional:

  • Media Players: mpv (default), vlc, or `tplay
  • Modern Terminal That Supports True Color:
    • kitty personal favourite; started the great terminal era lol
    • ghostty
    • wezterm
  • Terminal Image Viewers:
    • chafa (Cross-terminal)
    • icat (Recommended for Kitty and Ghostty)
    • imgcat (For iTerm2/WezTerm)
  • Alternate Launcher: rofi (Great if you want a desktop app launcher, you could even keybind the command, its really cool).
  • Terminal QoL:
    • gum (Better terminal ui; loaders, prompts etc).
    • bat to show update diffs in a nicer way

Universal Installation

Ensure ~/.local/bin exists and is added to your system's $PATH.

curl -sL "https://raw.githubusercontent.com/Benexl/yt-x/refs/heads/master/yt-x" -o ~/.local/bin/yt-x
chmod +x ~/.local/bin/yt-x

To uninstall ,just run: rm ~/.local/bin/yt-x, then to remove its related data folders rm -r ~/.config/yt-x and rm -r ~/.cache/yt-x.


Platform-Specific Instructions

Note am not the one who maintains any of this packages and you should probably turn off auto updates if using them

Arch Linux (AUR)
yay -S yt-x-git

# or if you prefer paru

paru -S yt-x-git
Nix / NixOS

1. Imperative:

nix profile install github:Benexl/yt-x

2. Declarative: First, add the repository to your flake.nix inputs:

inputs = {
  nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
  yt-x = {
    url = "github:Benexl/yt-x";
    inputs.nixpkgs.follows = "nixpkgs";
  };
}
  • For system-wide installation (in configuration.nix):

    environment.systemPackages = [ inputs.yt-x.packages."${system}".default ];
  • For user-level installation (via Home Manager in home.nix): nix home.packages = [ inputs.yt-x.packages."${system}".default ];

Usage

You can opt to either us it via menus or cmdline shortcuts for purposes of scripting or keybinding

yt-x [OPTIONS]
yt-x [OPTIONS] channels [CHANNEL OPTIONS]
yt-x completions [--fish | --bash | --zsh | --help]

Quick Start

To launch the interactive terminal interface with your default settings, run:

yt-x

Command‑Line Options

Search

If you don't pass an argument to any of this options you will be prompted for the term

  • -s, --search <term> : Immediately execute a video search and bypass the main menu. (supports search history completion)
  • -sp, --search-playlist <term> : Immediately execute a playlist search.
  • -sc, --search-channel <term> : Immediately execute a channel search.
  • -ss, --search-short <term> : Immediately execute a short search.
  • -sm, --search-movie <term> : Immediately execute a movie search.

Access saved items

The values must be exact to the ones in the respective json files, completions make this easy All of them support tab completion for the saved items

  • -cp, --custom-playlist <name> : Open a specific custom playlist by its saved name
  • -cc, --custom-cmd <name> : Execute a specific custom command by its saved name
  • -sv, --saved-video <title> : Open a specific saved video by its title

Ui

  • -l, --launcher <fzf|rofi> : Override the default menu launcher.
  • --preview : Enable the preview window (images/text)
  • --no-preview Disable the preview window
  • --preview-images Enable the image preview
  • --no-preview-images Disable the image preview
  • -ce, --cmd-exit : Exit after shortcut menu command‑line options (useful for scripting).
  • -ps, --playlist-skip : Skip the playlist selection menu and automatically pick the first entry in a playlist.
  • -me, --media-exit : Exit after performing a media action (watch, listen, download, etc.).

Media Action Shortcuts (skip the media action menu)

All this options can be paired with --media-exit and after the media cmd is executed the cli terminates

  • --play : Immediately watch the selected video (you still choose from the list).
  • --play-all : Immediately play the whole playlist (implies --playlist-skip).
  • --listen : Immediately listen to the audio of the selected video.
  • --listen-all : Immediately listen to the whole playlist ( implies --playlist-skip).
  • --download : Download the selected video.
  • --download-all : Download the whole playlist (implies --playlist-skip).
  • --download-audio : Download only the audio of the selected video.
  • --download-audio-all : Download the whole playlist as audio (implies --playlist-skip).
  • --save : Save the selected video to your local saved videos list so you can watch it later without needing to download it.
  • --save-playlist : Save the current playlist to your custom playlists for the same reasons as above without needing an acc (implies --playlist-skip).
  • --shell : Open a subshell with the current state variables. (you can use it run custom cmds on the results yt-x has gotten)

Player & Playback

  • -p, --player <mpv|vlc|tplay> : Specify the media player
  • --mpv-args : Pass custom mpv args at runtime
  • --vlc-args : Pass custom vlc args at runtime
  • --tplay-args : Pass custom tplay args at runtime
  • --disown-player : Detach the player process from the terminal (allows you to keep browsing while watching).
  • --no-disown-player : Keep the player attached to the terminal session (default).

Direct Shortcuts (skip the main or miscellaneous menus)

All this options can be paired with --cmd-exit so that the start of the menus changes to the shortcuts so going back will exit the cli

  • --feed : Open your personalised feed immediately.
  • --subscriptions-feed : Open the subscriptions feed.
  • --watch-later : Open your Watch Later playlist.
  • --playlists : Browse saved YouTube playlists.
  • --custom-playlists : Browse custom playlists you've saved.
  • --saved : Open saved videos.
  • --recent : Show recently watched videos.
  • --liked : Open your Liked Videos playlist.
  • --watch-history : Show your watch history.
  • --clips : Browse your clips.
  • --new-custom-cmd : Jump straight to creating a custom command.
  • --custom-cmds : Execute an existing custom command.
  • --search-history : Browse your search history.
  • --edit-search-history : Edit the search history file.
  • --edit-custom-playlists : Edit the custom playlists JSON file.
  • --edit-mpv-config : Edit mpv’s configuration.
  • --edit-yt-dlp-config : Edit yt‑dlp’s configuration.
  • --edit-custom-cmds : Edit the custom commands JSON file.

Rofi

Note there are rofi themes in repo which you can use i customized them to make the experience just cool At least thats what i think you be the judge lol

  • --rofi-theme-main <path>
  • --rofi-theme-preview <path>
  • --rofi-theme-prompt <path>
  • --rofi-theme-confirm <path>
  • --rofi-theme-pager <path>

Others

  • -x, --extension <ext> : Load a specific extension file (absolute path or relative to ~/.config/yt-x/extensions/; supports fish tab complete).
  • -e, --edit-config : Open the yt-x configuration file in your $EDITOR.
  • -U, --update : Check for and apply the latest script update from GitHub.
  • -E, --generate-desktop-entry : Print a .desktop application entry to stdout; its pretty cool esp with the rofi theme in github repo for example.
  • -v, --version : Print version information and exit.
  • -h, --help : Show the help message and exit.
  • --config-write : Write the current runtime config to the config file

Channels Subcommand

Works only for subscribed to channels Its pretty useful for creating shortcuts and aliases to your favourite channels

yt-x [OPTIONS] channels [OPTIONS]

Options:

  • -n, --name <channel> : Specify the channel name (exact match, case‑sensitive; tab complete supported).
  • -s, --search <query> : Search within the channel’s uploads.
  • -v, --videos : List the channel’s uploaded videos.
  • -f, --featured : Show the channel’s featured playlists.
  • -p, --playlists : List the channel’s playlists.
  • -sh, --shorts : Show the channel’s shorts.
  • -st, --streams : Show live streams & past broadcasts.
  • -po, --podcasts : Show the channel’s podcasts.

Examples:

yt-x channels                                  # Pick from subscriptions interactively
yt-x channels -n "Linus Tech Tips" -v          # Browse latest videos
yt-x channels -n "iambenexl" -s "Top linux tools"   # Search inside a channel
yt-x channels -n "StarTalk" -p             # Show channel playlists
yt-x channels -n "The PrimeTime" -st            # Show channel streams
yt-x --cmd-exit channels -n 'freeCodeCamp.org' -p # Browse freecodecamp playlists and immediately exit on back
yt-x --cmd-exit channels -n 'freeCodeCamp.org' # useful for setting aliases eg a shortcut to always go to freecodecamp channel `freecodecamp`
yt-x --launcher rofi --cmd-exit channels -n 'freeCodeCamp.org' # or as an app eg  `freecodecamp-app`

Inline Search Syntax & Filters

When entering a search query (either via the -s flag or within the interactive prompt) Currently only one at a time is supported

  • Time: :hour, :today, :week, :month, :year
  • Format: :video, :movie, :live, :short, :long
  • Quality/Features: :4k, :hd, :hdr, :360, :vr, :3d, :local, :subtitles
  • Sorting: :newest, :views, :rating

Example: :4k pbs eons or at the end news :today

History Recall is also supported for both (Bang Syntax)

  • !1 : Re‑run your most recent search.
  • !2 : Re‑run your second most recent search, etc.

Environment Variables

Almost all CLI options can be permanently set in ~/.config/yt-x/config or overridden using environment variables.

  • YT_X_LAUNCHER (e.g., fzf or rofi)
  • YT_X_PLAYER (e.g., mpv)
  • YT_X_ENABLE_PREVIEW (true or false)
  • YT_X_ENABLE_PREVIEW_IMAGES (true or false)
  • YT_X_IMAGE_RENDERER (chafa, icat, imgcat)
  • YT_X_BROWSER (e.g., firefox, brave )

Examples & Workflows

Hello world

# always put --config-write at the end
# it will first save the runtime config and proceed with normal execution of the command
YT_X_IMAGE_RENDERER=icat YT_X_BROWSER=firefox yt-x --preview --preview-images --config-write

Desktop app launcher

Launch yt-x as a graphical application using Rofi Its really cool esp with the custom themes in the repo, so be sure to try

# allowing the player to run in the background when using rofi
# is a bad idea since the player will launch and rofi will launch again and block it
yt-x --launcher rofi --preview --preview-images --no-disown-player

Audio only background music

yt-x -l fzf -p mpv --disown-player --listen-all -sp "lofi hip hop radio" # skip playlist results menu
# or
yt-x -l fzf -p mpv --disown-player --listen -sp "lofi hip hop radio" # choose specific video to listen to

Binge your watch later

yt-x --play-all --watch-later

Save the playlist and exit

yt-x --save-playlist --media-exit --search-playlist "anatomy"

Download playlist and exit

yt-x --download-all --media-exit --search-playlist "general relativity"

Search a channel and play a video

# though i already think its obvious lol
yt-x channels -n "Linus Tech Tips" -s "linux or mac" --play

create a desktop entry

yt-x -E > ~/.local/share/applications/yt-x.desktop

Shell completions

# NOTE: incase of updates the completions may change or more maybe added
yt-x completions --fish > ~/.config/fish/completions/yt-x.fish

listen to a saved video

yt-x --listen --media-exit -sv "podcast"

listen to a custom playlist

# you could easily keybind this
yt-x --launcher rofi --no-disown-player --listen-all --media-exit -cp "study music"

Explore a custom sites playlist and play the video

# you could easily keybind this
yt-x --launcher rofi --no-disown-player --play --media-exit -cc "my custom cmd for exploring a different streaming site that yt-dlp supports"

search for shorts and download

yt-x --download --media-exit -ss "linux meme"

Explore the latest news and play on selection

# you could easily keybind this
yt-x --launcher rofi --no-disown-player --play --media-exit -s ":today world news"

create convinience aliases

function play
    yt-x --play --media-exit $argv
end

funcsave play

play -s "Top Movies"

# you could do sth similar for zsh or bash
# if you want auto complete for play just dump the completions to play.fish and find and replace yt-x with play

# also do channel aliases
function freecodecamp
    yt-x --launcher fzf channel -n "freeCodeCamp.org" $argv
end

function freecodecamp-app
    yt-x --launcher rofi --no-disown-player channel -n "freeCodeCamp.org" $argv
end

funcsave freecodecamp

freecodecamp --search "how llms work"

Configuration

By default, the main configuration file is located at:

~/.config/yt-x/config

(Note: It respects the $XDG_CONFIG_HOME environment variable if set).

You can open it using the cli

yt-x --edit-config

Configuration Variables

Display & Interface

Variable Default Description
CONFIG_LAUNCHER fzf The menu launcher tool to use. Options: fzf or rofi.
CONFIG_ENABLE_COLORS true Enable or disable ANSI true-color (24-bit) formatting in the UI.
CONFIG_PER_PAGE 30 Maximum number of search/list results to fetch and display per page.
CONFIG_EDITOR vi (or $EDITOR) Text editor used for editing config files, histories, and extensions.
CONFIG_NOTIFICATION_DURATION 5 Duration (in seconds) for desktop/CLI notifications to remain visible.

Media Previews

Variable Default Description
CONFIG_ENABLE_PREVIEW false Enable or disable the preview window (metadata & descriptions).
CONFIG_ENABLE_PREVIEW_IMAGES false whether to render thumbnails in the preview window.
CONFIG_IMAGE_RENDERER chafa Tool used to render images in the terminal. Options: chafa, icat, imgcat.
CONFIG_CHAFA_ARGS "" Pass custom arguments to chafa (e.g., --polite on).
CONFIG_ICAT_ARGS "" Pass custom arguments to icat / kitty +kitten icat.
CONFIG_IMGCAT_ARGS "" Pass custom arguments to imgcat.

Playback & Media Handling

For configuring a player prefer its config file which you can also edit from why yt-x in the misc menu They exist purely for convinience and is more useful when passing from cmdline or env vars

Variable Default Description
CONFIG_PLAYER mpv Preferred media player. Options: mpv, vlc, tplay.
CONFIG_DISOWN_PLAYER false Set to true to run the player in the background without blocking the UI.
CONFIG_MPV_ARGS "" Custom arguments passed directly to mpv.
CONFIG_VLC_ARGS "" Custom arguments passed directly to vlc.
CONFIG_TPLAY_ARGS "" Custom arguments passed directly to tplay.

yt-dlp

Variable Default Description
CONFIG_BROWSER "" Which browser yt-dlp should use to get browser cookies to access private playlists etc
CONFIG_YT_DLP_ARGS "" pass custom arguments though prefer yt-dlp config file

Downloading

Variable Default Description
CONFIG_DOWNLOAD_DIR ~/Videos/yt-x Base directory where all downloaded videos and audio files are saved.
CONFIG_DOWNLOADS_ENUMERATE false Set to true to prepend numbers (01 -, 02 -) to downloaded playlist items.

History & Caching

Variable Default Description
CONFIG_ENABLE_SEARCH_HISTORY true Save local search history to track and quickly recall past queries.
CONFIG_NO_OF_RECENT 10 The number of recent "Watch History" items to retain locally.
CONFIG_CACHE_RETENTION_DAYS 7 Auto-clean stale preview images, autogen playlists, and logs older than this duration.

Fzf and Rofi

Check the repo for pre-configured rofi themes

Variable Default Description
CONFIG_FZF_HEADER (logo) A custom header string displayed at the top of the fzf menu (defaults to the yt-x ASCII logo).
CONFIG_FZF_OPTS (see config) Fine‑tune fzf layout, colors, pointers, and keybindings. Defaults to "Tokyo Night" .
CONFIG_ROFI_THEME_MAIN "" Path to a custom Rofi .rasi theme for the main menu.
CONFIG_ROFI_THEME_PREVIEW "" Path to a custom Rofi .rasi theme for the preview menu.
CONFIG_ROFI_THEME_PROMPT "" Path to a custom Rofi .rasi theme for prompt dialogs.
CONFIG_ROFI_THEME_CONFIRM "" Path to a custom Rofi .rasi theme for confirmation dialogs.
CONFIG_ROFI_THEME_PAGER "" Path to a custom Rofi .rasi theme for the pager.

Others

Variable Default Description
CONFIG_AUTOLOADED_EXTENSIONS "" Comma-separated list of extension scripts to load automatically on startup.
CONFIG_CHECK_FOR_UPDATES true Periodically check the GitHub repository for updates and prompt to install.

Frequently Asked Questions (FAQ)

Is yt-x a standalone media downloader or player? (Reporting Bugs)

No. yt-x is just a wrapper over amazing cmdline tools. (yt-dlp,fzf,rofi,mpv etc) Before opening an issue on GitHub, please determine if the bug is actually related to yt-x or one this tools

For example:

  • Media Fetching/Downloading fails: This is handled by yt-dlp. If a specific site breaks or videos refuse to download, try updating yt-dlp first (yt-dlp -U).
  • State management, navigation, or UI/preview logic fails: This is handled by yt-x. Please open an issue!
How do I access age-restricted or members-only videos?

You need to pass your browser cookies to yt-dlp. You can do this natively in yt-x by editing your config (~/.config/yt-x/config) and setting the CONFIG_BROWSER variable to your a supported browser by yt-dlp (e.g., firefox, chrome, brave).

Note: you can also configure your media player to use these cookies (see the MPV optimization tip below).

How can I optimize MPV playback (Quality, Cookies, Hardware Decoding)?

By default, mpv handles streaming via yt-dlp under the hood. To ensure mpv uses your browser cookies and defaults to 1080p hardware-accelerated playback, add something like this to your ~/.config/mpv/mpv.conf: You can also do it from the miscellaneous menu

# Pass cookies to yt-dlp inside mpv
# Force highest quality 1080p video + best audio
# plus handle subs
# you could also add sponsor block and chapters
# by adding --embed-chapters --sponsorblock-mark all to the list
ytdl-raw-options=format-sort="res:1080,vcodec:vp9,acodec:opus,fps",sub-lang="en,eng,enUS,en-US",write-sub=,write-auto-sub=,cookies-from-browser=firefox
ytdl-format=bestvideo+bestaudio/best

# if you know the exact decoder specify it vaapi for intel gpus or i think *nvdec for nvidia gpus
hwdec=auto
vo=gpu

# subs
slang=en,eng,enUS,en-US
sub-auto=fuzzy
What yt-dlp config do you use?

Something like this

# though format sort would be better just recently discovered it lol check the mpv faq above to see how or the official readme
-f bestvideo[height=1080][fps=60][vcodec^=vp9]+bestaudio/best[height=1080][fps=60][vcodec^=hevc]+bestaudio/best[height=1080][fps=60][vcodec^=avc1]/bestvideo[height=1080][fps<=30][vcodec^=vp9]+bestaudio/best[height=1080][fps<=30][vcodec^=hevc]+bestaudio/best[height=1080][fps<=30][vcodec^=avc1]/bestvideo[height>=720][height<1080][fps=60][vcodec^=vp9]+bestaudio/best[height>=720][height<1080][fps=60][vcodec^=hevc]+bestaudio/best[height>=720][height<1080][fps=60][vcodec^=avc1]/bestvideo[height>=720][height<1080][fps<=30][vcodec^=vp9]+bestaudio/best[height>=720][height<1080][fps<=30][vcodec^=hevc]+bestaudio/best[height>=720][height<1080][fps<=30][vcodec^=avc1]/bestvideo[height>=720]+bestaudio/best
--embed-chapters
--sponsorblock-mark all
--embed-metadata
--embed-thumbnail
--add-metadata
--embed-subs
--sub-lang en
--merge-output-format mkv
--no-warnings
--quiet
--reject-title "\[Deleted video\]|\[Private video\]"
How do i filter out deleted or private videos?

Add something like this to yt-dlp config

--reject-title "\[Deleted video\]|\[Private video\]"
Why are my image previews not showing up?

Image previews require a few components to work together:

  1. Ensure you have enabled them in your config: CONFIG_ENABLE_PREVIEW=true and CONFIG_ENABLE_PREVIEW_IMAGES=true.
  2. Ensure you have a supported image renderer installed (e.g., chafa, icat, or imgcat).
  3. Set the correct renderer in your config: CONFIG_IMAGE_RENDERER="chafa".
  4. Ensure your terminal emulator actually supports image rendering (sixel, kitty graphics protocol, or iTerm2 protocol). If it doesn't, stick with chafa, which falls back to excellent ASCII/block character rendering.
How do I fix "Cannot decrypt v11 cookies", Flatpak, or unsupported browser errors?

yt-x passes the CONFIG_BROWSER variable directly to yt-dlp.

  • Chromium v11+ / Brave / Edge: Modern Chromium browsers encrypt cookies via your OS keyring (GNOME Keyring, KWallet). yt-dlp needs access to this keyring to decrypt them.
  • Flatpaks / Snaps: yt-dlp cannot easily read cookies from containerized browsers due to sandboxing. Use natively installed browsers (deb/rpm/AUR/Homebrew) for the best cookie compatibility.
  • Alternative: If your browser (like Zen) isn't supported natively, use an extension like "Get cookies.txt LOCALLY", save the file, and pass it via your config: CONFIG_YT_DLP_ARGS="--cookies /path/to/cookies.txt".
How do i set qute-browser in my config?
CONFIG_BROWSER="chromium:~/.local/share/qutebrowser"
Previews overlap text or look distorted. How do I fix this?

If your images are overlapping with UI text, your terminal may not properly support the image clearing sequences used by chafa.

  1. Kitty / Ghostty: Set CONFIG_IMAGE_RENDERER="icat".
  2. iTerm2 / WezTerm: Try CONFIG_IMAGE_RENDERER="imgcat".
  3. Other Terminals: Stick to CONFIG_IMAGE_RENDERER="chafa", but ensure your terminal supports Sixel or true-color ASCII. If overlaps persist, disable image previews (CONFIG_ENABLE_PREVIEW_IMAGES=false) and use text-only previews.

also make sure to delete the ~/.cache/yt-x/previews/text/fzf-preview.sh file to clear out old cached values that may have been generated with the wrong renderer settings

How do I add Vim motions (j/k) or change menu keybindings?

Since the UI is driven by fzf, you can easily customize keybindings by modifying the CONFIG_FZF_OPTS variable in your ~/.config/yt-x/config file. Add --bind flags to map your preferred keys. For example, to add Vim motions and page scrolling:

CONFIG_FZF_OPTS="...your existing options... --bind 'j:down,k:up,ctrl-u:half-page-up,ctrl-d:half-page-down'"
How do I return to the menu while a video is playing?

By default, yt-x blocks the terminal until the media player is closed. To browse while watching, enable background playback by setting CONFIG_DISOWN_PLAYER=true in your config, or launch the script with the --disown-player flag.

I'm on macOS and getting `command not found`, parser errors, or `jq` errors.

macOS ships with an outdated version of Bash (v3.x) This is due to licensing issues and mac being mac you cant even remove it apparently 😂 Ensure you have installed the core dependencies via Homebrew (brew install bash). Homebrew's installation location should be at the top of path so its preferred over the older bash which you cant remove

Currently working on figuring out whats the syntax issue preventing the script from working with 3.x but for security reasons, even when the script supports it, prefer the latest version for daily use ohh and any help on the 3.x issue would be appreciated

Why is a video playing in the wrong quality (e.g., 4K instead of 1080p) or throwing "Requested Format not available"?

Configure your media player. Add something like this to your ~/.config/mpv/mpv.conf: ytdl-format="bestvideo[height<=?1080]+bestaudio/best"

I have no audio when playing videos on Termux / Android.

On Android, yt-x does not play the media inside the terminal. Instead, it uses Android am start intents to pass the stream URL to an installed GUI application (like the VLC or MPV Android apps).

Since you can't directly use the mpv command in termux unless you have installed a window manager so apps like mpv and vlc android are used through android intents api and there it only supports giving it one url

the script uses --get-url yt-dlp opt inorder to get the url but only picks the top one for video where the second maybe the audio file if the video has a separate audio file

so to 'fix' this you only need to specify --format yt-dlp opt in your config where you specify merged formats like best --format 'best'

in case someone figures out how to also pass an audio file(more than one url) using android intents this will always limit what you can stream to only merged files and incase you do please share :)

I'm getting "Malformed State" or "Invalid Action" errors constantly.

Its either a bug or you pressed ctrl+c too fast and it triggered the state dir to be wiped by trap cmd

I customized my colors and now the script crashes with "Invalid color specification".

This is an fzf error especially in debian systems where the fzf version maybe older. So just update it using more upto date ppa's or use Homebrew its what i used to use when i first started using linux (ubuntu) works supprisingly well

How do I populate the Channels/Subscriptions tab? It says my JSON is empty.

You need to sync your subscriptions first.

  1. Ensure CONFIG_BROWSER is set to the browser where you are logged into YouTube.
  2. Go to the Main Menu -> Miscellaneous -> Sync YouTube Subscriptions. yt-dlp will use your browser cookies to fetch your subscriptions and populate the ~/.config/yt-x/subscriptions.json file.
How can I get my system to display media metadata (title, artist) when using the "Listen" action?

This is actually a feature of your media player rather than yt-x. Integrating this directly into yt-x would require intercepting mpv's output using Lua scripts or enforcing playerctl + MPRIS , which i don't want to do nor think its a good idea

The Solution: The cleanest way to achieve this is by enabling MPRIS support directly in your media player.

  • For mpv: Install the mpv-mpris plugin. This allows mpv to broadcast the current track's metadata to your OS, exactly like a web browser does for YouTube.
  • For other players: Search for similar MPRIS or D-Bus integration plugins/settings.

Once configured, any compatible desktop widget or notification daemon will automatically pick it up and display what's playing. For example, this is how it looks in myNoctalia setup on Niri:

Noctalia MPRIS Example 1 Noctalia MPRIS Example 2 Noctalia MPRIS Example 3
How can I play or download something without any interactive menus? (Non‑interactive mode)

yt-x now supports several flags that let you bypass all menus and run actions non‑interactively – perfect for scripting, keybindings, or quick one‑off commands.

  • --playlist-skip (-ps) : Automatically picks the first item in any list (search results, playlist, etc.) without showing the selection menu.
  • --play-all, --listen-all, --download-all, --download-audio-all, --save-playlist : These implicitly enable --playlist-skip and act on the whole playlist immediately.
  • --media-exit (-me) : After performing a media action (play, download, save, etc.), exit the script.
  • --cmd-exit (-ce) : After processing any shortcut menu command (e.g., --feed, --subscriptions-feed), exit.

Examples:

# Play the first video from a search and exit
yt-x --playlist-skip --media-exit --play -s "Dota"

# Download the whole Watch Later playlist without any prompts
yt-x --download-all --watch-later

# Save the current playlist as a custom playlist and exit
yt-x --save-playlist --media-exit

read usage for more examples and cmdline docs

What is the `--shell` flag and when should I use it?

--shell(media action) drops you into a subshell that is pre‑loaded with all the current session’s state variables. Its useful for running custom cmds on the current results

Available variables in the subshell include:

  • STATE_CURRENT_VIDEO, STATE_CURRENT_VIDEO_URL, STATE_CURRENT_VIDEO_TITLE
  • STATE_CURRENT_PLAYLIST_RESULTS, STATE_CURRENT_PLAYLIST_URL, STATE_CURRENT_PLAYLIST_TITLE
  • Channel info, pagination indices, etc.

You can use this to, for example, manually run yt-dlp commands on the current video, extract metadata, or automate custom post‑processing. Note some are json so use jq to parse and inspect them or interactive ones like ijq and jnv

How do I override configuration settings using environment variables?

Every config variable can be overridden by an environment variable prefixed with YT_X_. This is useful for scripting or one‑off changes without touching the config file.

Examples:

# Use rofi as launcher for this session
YT_X_LAUNCHER=rofi yt-x

# Enable previews and use chafa for images
YT_X_ENABLE_PREVIEW=true YT_X_IMAGE_RENDERER=chafa yt-x

# Change download directory temporarily
YT_X_DOWNLOAD_DIR="$HOME/Downloads/temp" yt-x --download-all

See the config file for all available variables (e.g., YT_X_PLAYER, YT_X_BROWSER, YT_X_PER_PAGE, etc.).

what window manager is that and how do i make mine look like that?

i am using niri as my compositer and noctalia does all the theming for me. Though am planning to create my own riced setup when i gate free time, and maybe even a my own widget system which should also function as an sddm alternative since i personally dont like quickshell since its a resource hog and one of the reasons i like linux is low resource usage; especially since my first laptop was not powerful (celeron, 4gb ram, 1tb harddisk), so i still have the over optimizing mindset. I even have a name for it lol, i cant remember it now but i know it has an 'x' in it lol its probably going to be based on iced-rs and the config language rhai since i like its concept and prefer not to have to deal with ffi bindings of another lang so no lua. And i want it to be as stable as possible and no points of failure due to memory stuff

does that mean am a rust fanatic, nope just dont want to deal with a class of bugs and want to focus on logic though i still plan to master zig after rust since i like its concept of explicit memory management it helps in reducing cognitive overload in large systems and there are times where manual memory management is useful like when you need to squeeze every single bit of performance plus its syntax looks interesting

whats up with the half terminal?

its kitty's quake terminal mode, you can set one using quake-terminal kitten for kitty users. Other terminals also implement may also implement a similar feature.

How can i get mpv to look like the one in the demos (just look nicer)?

I personaly use uosc which in my opinion its by far the best ui for mpv. They have even implemented rendering yt's heatmap in the timeline. You can even also install thumbfast which will add timeline previews.

Why shell (4k+ lines) and not a language like python, go, rust etc?

Honestly, it was initially cause at the time the project where i first saw the concept was in bash magictape. Other than that i had know meaningful reason then. But now i can say its portability(runs in zsh, dash, bash, ksh; posix compliant systems) and its really easy to modify, audit and build upon a shell script since the excutable is just one file and you can open it up in your editor anytime or easily modify it to do what you want without having to open a pr have a fork etc. I have also grown to like writing shell scripts and the challenge involved its kinda cool and ais suck at writing it esp long ones lol, so yeah. You also get to implement your own state logic from scratch, data transformation pipelines, and such since there are no shell libraries which you can use to do the same managing a really long monolithic program and dealing with lack of certain data structures, being conscious on the commands you run since creating a process incurs an overhead

so its one hell of a learning xp

Incase you are wondering how to traverse it and explore it efficiently use a symbols search lsp(make sure you have installed bash-lsp) The code is structured and ordered into sections and each section is demarcated by a header so you could easily use code folding and it becomes drastically shorter while still knowing where you are all functions also have a namespace using the function name ui preview app etc there are also sub namespaces like fzf or rofi

The cognitive overload you get is high but still its pretty fun once you get used to it and an asset for getting use to mapping large systems entirely in your head and working with several constraints

Why did you decide to write your own version and not just use magic-tape?

Initially previews on kitty did not work and it took sometime before my issue was answered and solved, and a month later i decided to write my own on github

And thus in my first year, during orientation week, yt-x was born and became my second popular oss project.

Though whether you chose yt-x or magic-tape its upto you

Whats the point of releases if the script only checks for updates from the latest commit?

well non really just there to show the progression to a stable version v1.0.0. where i wont wake up one night with a ton of ideas and implement them before i go back to sleep the next day lol.

Other than that i dont think going forward there will be that many changes esp since the heavy lifting is done by its dependencies like yt-dlp. The script will proabably work for many years to come as long as yt-dlp exists, which i think it will. And ways the last major change i have made before v1.0.0 was the rewrite v0.5.0 which was done in a separate branch and took a week ~8hrs a day to write and i aint doing that again lol

Plus the update process is pretty transparent since you always get to see what changed. Which i think its unique to yt-x.

Why are there functions in the script which just call another function?

My goal with this was to make it easier to build ontop of a feature or menu without losing the original functionality eg in extensions. In other languages this would be trivial without need for the redundancy but in shell this is the best idea i have so far

Can i use the ui functions etc in the script for my own project or personal script?
yes
Why is feature x not implemented?

Well i only have so much time and i really do have to sleep lol such is the fate of organic lifeforms lol. Though prs are mighty welcomed

Like i have so many ideas, though i decided not to implement some due to the illusion of how long it will take like v0.5.0, thought i could do the rewrite in a day lol, ended up being a week working nearly most of the day. There are even somethings i mentioned i will do at the start of the pr that i got so tired i decided not to implement.

And for the same reason if you want to request a feature its fine, though whether i personally will implement it is entirely whether i find it interesting enough or i will use it.

Otherwise you will probably have to open a pr or wait for someone else to implement it

Why such a long faq?

well most of the issues that have been opened in github since before the faq are not related to yt-x itself and i thought why not just share all the knowledge i have on the tools the script is using or ones i have shown in my demos. Plus i remember how hard and long it took to solve some issues and want the script to be something you install and it just works.

Contribution

Pull requests are highly welcome :)

Supporting the Project

If you enjoy using yt-x and want to support its ongoing development, consider leaving a Star on GitHub!

About

Browse youtube from your terminal

Resources

License

Stars

Watchers

Forks

Contributors

Languages

  • Shell 99.5%
  • Nix 0.5%