A modern, interactive CLI for downloading YouTube videos and audio using yt-dlp. Built with Bun and TypeScript. Linux only.
- Interactive guided workflow — prompts for format, quality, subtitles, metadata, and more
- MP4 video downloads — with automatic audio/video merging via ffmpeg
- MP3 audio extraction — configurable bitrate (128/192/256/320 kbps)
- Batch downloads — download multiple videos via comma-separated URLs or from
.txt/.mdfiles - Playlist support — download entire playlists, first item, or select specific items with fuzzy search
- Browser cookie support — download age-restricted or private content using cookies from Chrome, Firefox, Edge, Brave, or Safari
- Presets — save and reuse download configurations (balanced, best quality, audio only, etc.)
- Subtitles — download and embed or save as separate files
- Metadata embedding — embed metadata, thumbnails, and chapters into output files
- Dry-run mode — preview resolved yt-dlp arguments without downloading
- Filename preview — see predicted output filename before downloading
- Artifact size estimation — estimated file size based on bitrate and duration
- aria2 support — optional multi-threaded downloading via aria2
- Doctor command — check runtime dependencies and configuration health
- XDG-compliant config — stored at
~/.config/ytx-downloader/config.json - Graceful shutdown — clean process termination on Ctrl+C
Linux only. This tool is designed and tested exclusively for Linux environments.
| Dependency | Required | Purpose |
|---|---|---|
| Bun | Yes | JavaScript runtime |
| yt-dlp | Yes | Download engine |
| ffmpeg | Yes | Format merging and audio extraction |
| aria2 | Optional | Faster multi-threaded downloads |
All dependencies must be available in your system PATH.
See the Linux Installation Guide for detailed per-distribution instructions.
# 1. Install Bun
curl -fsSL https://bun.sh/install | bash
# 2. Clone and install
git clone https://github.com/MuhammadAkbar11/ytx-ytdlp-media-toolkit.git
cd ytx-ytdlp-media-toolkit
bun install
# 3. Link the CLI globally
bun link
# 4. Verify installation
ytx --help
ytx doctorMake sure ~/.bun/bin is in your PATH:
export PATH="$HOME/.bun/bin:$PATH"Add the line above to your ~/.bashrc or ~/.zshrc to make it permanent.
# Interactive mode — guided prompts for format, quality, etc.
ytx download <URL>
# Audio-only (MP3)
ytx download <URL> --audio
# Video (quality selected interactively)
ytx download <URL> --video
# Use browser cookies for restricted content
ytx download <URL> --browser firefox/brave/chrome
# Dry-run — preview without downloading
ytx download <URL> --dry-runDownload multiple videos in a single command:
# Comma-separated URLs
ytx download "https://youtu.be/aaa,https://youtu.be/bbb,https://youtu.be/ccc"
# From a text file
ytx download --file urls.txt
# From a markdown file
ytx download --file urls.md
# Batch with preset and output directory
ytx download --file urls.txt --preset balanced --output ~/Videos- Playlist URLs are rejected in batch mode (use the playlist workflow instead)
- Duplicate URLs are automatically removed
- Downloads run sequentially, one at a time
- Files should contain one URL per line; markdown links (
[text](url)) are also supported
# View all config
ytx config get outputPath
# Set a value
ytx config set outputPath ~/Videos
# List current configuration
ytx config list
# Reset to defaults
ytx config reset# List available presets
ytx preset list
# Show preset details
ytx preset show balanced
# Set a default preset
ytx preset use balancedytx doctorChecks for yt-dlp, ffmpeg, aria2, config accessibility, and output directory writability.
Configuration is stored at:
$XDG_CONFIG_HOME/ytx-downloader/config.json
Falls back to ~/.config/ytx-downloader/config.json if XDG_CONFIG_HOME is not set.
Output paths are resolved in this order:
| Priority | Source | Example |
|---|---|---|
| 1 | --output <dir> CLI flag |
ytx download <URL> --output ~/Videos |
| 2 | outputPath in config |
ytx config set outputPath ~/Videos |
| 3 | ~/Downloads fallback |
auto-applied if above are invalid or unset |
Paths are normalized (~ expansion → absolute) and validated (exists + writable + is directory). Invalid paths fall through silently to the next option.
When a playlist URL is detected, ytx offers three options:
ytx download https://youtube.com/playlist?list=PLxxxxxx- Entire playlist — download all items
- First item only — download just the first video
- Select specific items — fuzzy search through playlist items with arrow keys
Some content requires authentication (age-restricted, private, or members-only videos).
# Prompted to select browser interactively
ytx download <URL> --browser
# Pass browser directly
ytx download <URL> --browser firefox/brave/chrome
# Set a default browser in config
ytx config set preferredBrowser firefoxSupported browsers: chrome, firefox, edge, brave, safari.
Enable multi-threaded downloading via aria2 for faster speeds:
ytx download <URL> --aria2Requires aria2 to be installed and on PATH.
When ytx detects it is not running in an interactive terminal (e.g., in scripts or CI):
- No interactive prompts are shown
- CLI flags and config values drive all decisions
- Output path uses
--outputflag → configoutputPath→~/Downloadsfallback - Missing required values produce clear error messages instead of prompting
# Scripted audio-only download to specific directory
ytx download "https://youtube.com/watch?v=xxxxx" --audio --preset balanced --output /tmp/dlConfig migration is fully automatic — no commands or manual steps required.
When you run any ytx command, the config file is loaded and its version is checked. If an older config version is detected, the migration chain runs before the command executes:
| Migration | What it does |
|---|---|
| v1 → v2 | Version bump (no data changes) |
| v2 → v3 | Renames the outputDirectory key to outputPath |
For example, if your config file still has the old outputDirectory field:
{
"version": 2,
"outputDirectory": "/home/user/Downloads"
}After migration it becomes:
{
"version": 3,
"outputPath": "/home/user/Downloads"
}A green console message appears when migration runs: ✔ Config migrated from v2 to v3.
If a config file fails validation after migration (e.g., corrupted or missing required fields), ytx resets to defaults and prints the validation errors.
To check your current config, run:
ytx config list# Clone
git clone https://github.com/MuhammadAkbar11/ytx-ytdlp-media-toolkit.git
cd ytx-ytdlp-media-toolkit
# Install dependencies
bun install
# Run in dev mode
bun run dev
# Run with hot-reload
bun run dev:hot# Run all tests
bun test
# Run in watch mode
bun test --watchbun run lint
bun run lint:fix
bun run format
bun run format:check- Linux only. Windows and macOS are not supported. No plans to add cross-platform support.
- Requires Bun runtime (>= 1.0.0) — Node.js is not supported.
yt-dlpmust be installed and on PATH. Version drift in yt-dlp can break download workflows.ffmpegis required for all video merging and audio extraction. No built-in fallback.aria2is optional but recommended for faster downloads. Single-threaded fallback works without it.
- Cookie extraction depends on the local browser installation and OS keychain access.
- Some browsers may require the browser to be closed before cookies can be read.
- Safari support is limited on Linux.
- Geo-restricted content requires a VPN or proxy — ytx does not provide proxy configuration.
- Age-restricted content requires browser cookies to be configured.
- Private/members-only content requires authenticated cookies from the correct account.
- Download speed depends on YouTube throttling, network conditions, and yt-dlp extraction quality.
- Config file is JSON-based. Manual edits with invalid JSON will cause a reset to defaults.
- Migration is one-way — downgrading from v3 to v2 config format requires manual intervention.
- Config version is checked on every command invocation (minimal overhead).
- Output path validation checks existence, writability, and directory type at runtime.
- Invalid paths fall through silently to the next option in the resolution chain.
- No support for custom filename templates via CLI (uses yt-dlp defaults).
- Large playlists may take time to inspect (depends on yt-dlp metadata fetching).
- Fuzzy search is in-memory — very large playlists (1000+ items) may feel slow.
- No telemetry, analytics, or phone-home behavior.
- No auto-update mechanism — updates require manual
git pull && bun install. - No plugin system or extension API.