yt-vod-manager Marco Hefti
winget install --id=MarcoHefti.YTVodManager -e CLI app to download YouTube channels and playlists and keep them up to date locally.
winget install --id=MarcoHefti.YTVodManager -e CLI app to download YouTube channels and playlists and keep them up to date locally.
A CLI app to download YouTube channels and playlists and keep them up to date locally.
It gives you simple daily commands, safe progress tracking, and optional background sync.
yt-dlp and ffmpeg):# macOS (Homebrew)
brew install yt-dlp ffmpeg
# Ubuntu/Debian example
sudo apt update
sudo apt install -y yt-dlp ffmpeg
yt-vod-manager (pick one):Homebrew:
brew tap marcohefti/yt-vod-manager
brew install yt-vod-manager
WinGet:
winget install --id MarcoHefti.YTVodManager; yt-vod-manager manage
npm:
npm install -g @marcohefti/yt-vod-manager
yt-vod-manager init
yt-vod-manager add --name mkbhd --source "https://www.youtube.com/@mkbhd/videos"
yt-vod-manager add --name my-playlist --source "https://www.youtube.com/playlist?list=PLFs19LVskfNzQLZkGG_zf6yfYTp_3v_e6"
yt-vod-manager sync --all-projects
yt-vod-manager status --all
If you see no projects configured, start with:
yt-vod-manager init
yt-vod-manager add --source ""
Think in three layers:
config/projects.json.runs// with manifests and state.sync does: refresh source from YouTube every run -> merge by video_id -> download pending/retryable jobs.This means you can stop and continue later without re-downloading completed videos.
yt-vod-manager list
yt-vod-manager manage
Manager controls:
up/down (or j/k) move selectionenter / e edit selected projectn create new project (wizard)d delete selected projectspace toggle active on selected projectActions panel and press enter on Sync Active Projects to launch syncActions panel and press enter on Global Settings to edit global defaultsleft/right or space toggle select/yes-no fields in the wizardq quitThe manager auto-adapts layout for narrow and wide terminals.
yt-vod-manager sync --project mkbhd
yt-vod-manager sync --all-projects
yt-vod-manager sync --all-projects --no-run
yt-vod-manager remove --name my-playlist --yes
yt-vod-manager settings show
yt-vod-manager settings set --workers 6 --download-limit-mb-s 80 --proxy-mode per_worker
yt-vod-manager settings proxy add --value "http://user:pass@proxy-1:8080"
yt-vod-manager self-update
The CLI also prints a periodic update hint after successful commands when a newer release exists.
Set YTVM_DISABLE_UPDATE_CHECK=1 to disable this (useful for CI/non-interactive automation).
--workers 5 download multiple videos in parallel (default is 5).add, --workers 0 means "inherit global/default workers".--fragments 10 stream chunks per video (default is 10).--download-limit-mb-s 80 cap transfer speed to 80 MB/s for this invocation (0 disables cap).--order oldest process oldest-first by default.--quality best|1080p|720p choose a simple quality preset.--subtitles auto|yes|no choose whether subtitles are downloaded.--sub-langs english|all choose subtitle language preference (default english).--browser-cookies use logged-in browser cookies for age-restricted videos.--active-only sync only projects marked active (with --project/--all-projects).--max-jobs 10 process only a limited batch.--retry-permanent re-attempt permanent failures.--stop-on-retryable stop cleanly after transient/rate-limit failures.--cookies /path/to/cookies.txt use authenticated access.--json print machine-readable output.Default config path: config/projects.json
Repository example: config/projects.example.json (safe template, no local secrets/paths).
Managed by:
initaddremoveEach saved source can keep defaults like workers/fragments/order/cookies/subtitle options.
Global settings in the same file (global) control:
proxy_mode=per_worker)Runtime precedence:
config/projects.jsonruns//manifest.raw.jsonmanifest.jobs.jsonrun.jsonruns//downloads/Most users only need init/add/list/sync/status/remove.
Advanced commands are still available for low-level control:
discoverrefreshrunFor refresh and run, target selection is explicit and safer:
--run-id --run-dir --project --latestrunning jobs are recovered as retryable.sync is safe for background execution. Use scripts/sync-active.sh (includes locking and --active-only defaults).
launchd): create ~/Library/LaunchAgents/com.marcohefti.yt-vod-manager-sync.plist that runs /absolute/path/to/yt-vod-manager/scripts/sync-active.sh, then launchctl load ~/Library/LaunchAgents/com.marcohefti.yt-vod-manager-sync.plist.systemd --user): create a marcohefti-yt-vod-manager-sync.service + marcohefti-yt-vod-manager-sync.timer that executes /absolute/path/to/yt-vod-manager/scripts/sync-active.sh, then systemctl --user enable --now marcohefti-yt-vod-manager-sync.timer.If you want to build locally instead of using npm/Homebrew:
yt-dlp, ffmpeg, and go):# macOS (Homebrew)
brew install yt-dlp ffmpeg go
# Ubuntu/Debian example
sudo apt update
sudo apt install -y yt-dlp ffmpeg golang-go
go build -o bin/yt-vod-manager ./cmd/yt-vod-manager
./bin/yt-vod-manager init
./scripts/verify.sh
This runs tests, architecture checks, linting, and build.
GitHub Releases are built automatically via .github/workflows/release.yml:
main -> versioned prerelease snapshot (v0.1.0-dev. initially; after vX.Y.Z, next snapshots use vX.Y.(Z+1)-dev.)v* -> normal versioned releaseCreate a release tag:
git tag v0.1.0
git push origin v0.1.0
Artifacts are attached to the release page:
darwin (amd64, arm64)linux (amd64, arm64)windows (amd64)checksums file for integrity verificationwinget-manifests_.zip (stable tags only)Homebrew:
brew tap marcohefti/yt-vod-manager
brew install yt-vod-manager
WinGet:
winget install --id MarcoHefti.YTVodManager
npm:
npm install -g @marcohefti/yt-vod-manager
For automation in GitHub Actions:
HOMEBREW_TAP_GITHUB_TOKEN (repo write access to marcohefti/homebrew-yt-vod-manager)WINGET_CREATE_GITHUB_TOKEN (GitHub PAT with public_repo scope for wingetcreate submit)@marcohefti/yt-vod-manager:
marcoheftiyt-vod-manager.github/workflows/release.ymlmicrosoft/winget-pkgs; after package MarcoHefti.YTVodManager exists, releases auto-submit updatesMIT (LICENSE).