Skip to content

jd-co/uld

Repository files navigation

ULD - Unified Local Downloader

A single CLI tool for downloading content from multiple sources: torrents, magnet links, video platforms, and direct URLs.

Python 3.10+ PyPI License: MIT

Why ULD?

I got tired of switching between different tools every time I needed to download something:

  • Need a YouTube video? Fire up yt-dlp with its flags
  • Downloading a torrent? Open qBittorrent or use libtorrent
  • Just a zip file? Back to wget or curl
  • An ISO from a mirror? Different command again

Each tool has its own syntax, options, and quirks to remember. I wanted one command that just works for everything.

So I built ULD - paste any URL, and it figures out the rest.

Before After
yt-dlp "https://youtube.com/..." uld <url>
qbittorrent magnet:?xt=... uld <url>
wget https://example.com/file.zip uld <url>
curl -O https://... uld <url>

ULD auto-detects the URL type and uses the right engine automatically.


Installation

Prerequisites

Install ULD

pip install uld-cli

That's it! Both video (yt-dlp) and torrent (libtorrent) support are included.

Using uv (faster):

uv add uld-cli

Quick Start

Step 1: Download anything

# YouTube video
uld "https://youtube.com/watch?v=dQw4w9WgXcQ"

# Magnet link
uld "magnet:?xt=urn:btih:..."

# Torrent file
uld ./ubuntu-24.04.torrent

Step 2: Watch the progress

Press q or Ctrl+C to stop or exit
⠋ Downloading [████████████░░░░░░░░] 60% 125.0 MB 5.2 MB/s 0:02:30

Step 3: Done!

✓ Download complete! Saved to: ~/Downloads/video.mp4
Downloaded: 208.5 MB | Duration: 1m 23s | Avg speed: 2.5 MB/s

Usage Examples

Videos

# Best quality (default)
uld "https://youtube.com/watch?v=..."

# Specific quality
uld "https://youtube.com/watch?v=..." -Q 720p

# Download entire playlist
uld "https://youtube.com/playlist?list=..."

# Just get info (no download)
uld info "https://youtube.com/watch?v=..."

Playlist Progress:

✓ [1/5] First Video Title 45.2 MB
✓ [2/5] Second Video Title 32.1 MB
⠋ [3/5] Third Video Title [████████░░░░] 45% 5.2 MB/s

Resume Support: If you stop a playlist download (q or Ctrl+C) and run the same command again, it automatically skips already downloaded videos and continues from where it left off.

Torrents

# Magnet link
uld "magnet:?xt=urn:btih:..."

# Torrent file
uld ./file.torrent

# Download without seeding
uld "magnet:..." --no-seed

# Custom seed ratio
uld "magnet:..." --seed-ratio 2.0

# Just get torrent info
uld info "magnet:?xt=urn:btih:..."

Output Options

# Custom output directory
uld "https://youtube.com/watch?v=..." -o ~/Videos

# Quiet mode (errors only)
uld "magnet:..." -q

# Verbose mode (debug info)
uld "magnet:..." -v

Commands Reference

Command Description
uld <url> Download from URL (auto-detects type)
uld download <url> Same as above (explicit)
uld info <url> Show metadata without downloading
uld engines List available engines and status
uld config Show current configuration
uld --help Show help

Download Options

Option Short Description
--output -o Output directory
--quality -Q Video quality (best, 1080p, 720p, 480p, 360p, worst)
--playlist -P Force playlist download
--seed-ratio -r Torrent seed ratio (default: 1.0)
--no-seed Don't seed after torrent download
--quiet -q Minimal output
--verbose -v Verbose output

Controls

While downloading, you can:

Key Action
q Stop download and exit
Ctrl+C Stop download and exit

Configuration

Set defaults via environment variables:

# Default download directory
export ULD_DOWNLOAD_DIR=~/Downloads/uld

# Default seed ratio (0 = no seeding)
export ULD_SEED_RATIO=1.0

# Rate limits in KB/s
export ULD_DOWNLOAD_RATE_LIMIT=1000
export ULD_UPLOAD_RATE_LIMIT=500

All Settings

Variable Default Description
ULD_DOWNLOAD_DIR ~/Downloads Default download directory
ULD_SEED_RATIO 1.0 Seed ratio (0 = no seeding)
ULD_SEED_TIME 0 Seed time in minutes
ULD_MAX_CONNECTIONS 200 Max peer connections
ULD_DOWNLOAD_RATE_LIMIT 0 Download limit KB/s (0 = unlimited)
ULD_UPLOAD_RATE_LIMIT 0 Upload limit KB/s (0 = unlimited)
ULD_ENABLE_DHT true Enable DHT for torrents
ULD_ENABLE_UPNP true Enable UPnP

Supported Platforms

Video Sites (1000+ supported)

  • YouTube (videos & playlists)
  • Vimeo
  • Twitter/X
  • Reddit
  • Instagram
  • TikTok
  • Twitch
  • And many more... (powered by yt-dlp)

Torrent

  • Magnet links
  • .torrent files (local or HTTP URLs)

Programmatic Usage

You can use ULD as a library in your Python code:

Basic Download

from uld import download

# Download from any supported URL
result = download("https://youtube.com/watch?v=dQw4w9WgXcQ")
print(f"Saved to: {result.file_path}")
print(f"Size: {result.total_downloaded} bytes")

With Progress Callback

from uld import download, DownloadProgress

def on_progress(p: DownloadProgress):
    print(f"{p.percentage:.1f}% - {p.speed_human}")

result = download(
    "https://youtube.com/watch?v=...",
    output_dir="./videos",
    quality="720p",
    progress_callback=on_progress,
)

Get Metadata Without Downloading

from uld import get_info

# Video info
info = get_info("https://youtube.com/watch?v=...")
print(f"Title: {info['title']}")
print(f"Duration: {info['duration']} seconds")

# Torrent info
info = get_info("magnet:?xt=urn:btih:...")
print(f"Name: {info['name']}")
print(f"Size: {info['total_size']} bytes")

Check Available Engines

from uld import get_available_engines

for engine in get_available_engines():
    status = "✓" if engine.available else "✗"
    print(f"{status} {engine.name}: {engine.version or 'not installed'}")

Torrent Options

from uld import download

result = download(
    "magnet:?xt=urn:btih:...",
    output_dir="./downloads",
    seed_ratio=0,       # Don't seed after download
    # seed_ratio=2.0,   # Seed until 2:1 ratio
    # seed_time=30,     # Seed for 30 minutes
)

Development

# Clone
git clone https://github.com/jd-co/uld.git
cd uld

# Install with dev dependencies
uv sync --all-extras

# Run tests
uv run pytest

# Run linter
uv run ruff check src tests

# Format code
uv run ruff format src tests

Contributing

Contributions are welcome! Here's how to get started:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests and linting:
    uv run pytest
    uv run ruff check src tests
    uv run ruff format src tests
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to your branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

Guidelines

  • Follow existing code style (enforced by ruff)
  • Add tests for new features
  • Update documentation as needed
  • Keep PRs focused on a single change

Ideas for Contributions

  • Bug fixes and improvements
  • Support for new download sources
  • Documentation improvements
  • Performance optimizations

License

MIT License - see LICENSE for details.

Acknowledgments

Built with these amazing projects:

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages