The Torrent Builder is a command-line tool for creating torrent files, offering a complete and customizable experience. With support for interactive and non-interactive modes, you can create torrents quickly and efficiently, either through a step-by-step wizard or with direct commands. The tool allows you to configure various aspects of the torrent, such as version (V1, V2, or Hybrid), comments, privacy, web seeds, and trackers, ensuring your torrents are created exactly as you need them.
- Create torrent files from single files or directories
- Inspect existing torrent files (metadata, file tree, verification, magnet link)
- Modify existing torrent metadata without re-hashing file content
- Support for torrent versions: V1, V2, and Hybrid
- Interactive mode with step-by-step configuration
- Command-line interface with options for all features
- Automatic piece size calculation based on file size
- Manual piece size configuration
- Support for private torrents
- Add multiple trackers and web seeds
- Include comments in torrent metadata
- Cross-seeding support: source field and info hash randomization
- Detailed summary output after creation
- Verbose mode for detailed creation diagnostics
- Quiet mode for scripts and CI pipelines
- JSON output for programmatic consumption
- Auto-naming: output filename generated from tracker domain and content name
- Collision-safe naming: automatically resolves filename conflicts with
(1),(2), etc. - Filename truncation with UTF-8 boundary safety (255-byte filesystem limit)
- YAML-based preset system for per-tracker configuration
- Batch mode: create multiple torrents in parallel from a YAML config
- Configurable output directory (auto-created if needed) and tracker index for filename prefix
- Season pack detection: warn or fail on incomplete TV season packs (missing episodes)
- Self-update: check for and install the latest version from GitHub Releases
- C++23 Compiler: GCC 13+, Clang 15+.
- CMake: >= 3.28
- libtorrent-rasterbar: >= 2.0.10 (for C++17/20+ support and compatibility)
- pkg-config: Required for libtorrent detection via PkgConfig in CMake
- Build Tools: Varies by OS (see below)
Ubuntu/Debian
sudo apt install build-essential cmake libtorrent-rasterbar-dev pkg-config libssl-dev
Fedora
sudo dnf install gcc-c++ cmake rb_libtorrent-devel openssl-devel
brew install cmake libtorrent-rasterbar openssl@3
To build, you need a compatible C++23 compiler (see Prerequisites). CMake will automatically check and display a clear error if the compiler is inadequate (e.g., GCC < 13).
mkdir build
cd build
cmake ..
cmake --build .
For an optimized Release build: cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build ..
On macOS, pass the OpenSSL path to CMake since openssl@3 is keg-only:
cmake .. -DOPENSSL_ROOT_DIR=$(brew --prefix openssl@3)
Note: The executable will be generated at build/torrent_builder. For debugging, use -DCMAKE_BUILD_TYPE=Debug. If pkg-config fails, check your installation in Prerequisites.
Versioning: When building from a git tag (e.g., v0.2.0), the version is automatically detected. Otherwise, the version defaults to dev. You can override with -DTORRENT_BUILDER_VERSION=x.y.z during cmake configuration. Use ./torrent_builder --version to check.
./torrent_builder -i./torrent_builder --path /path/to/file_or_directory [options]./torrent_builder inspect file.torrent [options]./torrent_builder modify file.torrent [options]Edit metadata of an existing .torrent file in-place without re-hashing file content. Supports V1, V2, and hybrid torrents. Changes are written atomically (temp file + rename).
Note:
--outputis optional. When omitted, the output filename is auto-generated from the tracker domain and content name (e.g.,tracker.example.com_myfile.torrent).
./torrent_builder batch batch.yaml [--workers N]Process multiple torrent creation jobs from a YAML config file in parallel. See the Batch Mode section below for details.
./torrent_builder update [options]Check for newer versions and update the binary in-place from GitHub Releases. Downloads are verified against SHA-256 checksums published in each release's checksums.txt.
Note: Requires
curlto be installed and available on the system PATH. On macOS,unzipis also required.
Tip: If you hit GitHub API rate limits, set the
GITHUB_TOKENenvironment variable with a personal access token to use authenticated requests.
Options:
-h, --help Show help and usage
--check Only check for available updates (no download)
-y, --yes Skip confirmation prompt
--rollback Restore previous version from backup
Examples:
# Check and install the latest version
./torrent_builder update
# Only check if an update is available
./torrent_builder update --check
# Update without confirmation prompt (useful for scripts)
./torrent_builder update --yes
# Restore the previous version after an update
./torrent_builder update --rollbackOn startup, the default creation flow performs a best-effort check (short
timeout, at most once per 24 h) for a newer
release and prints a notice to stderr (so --json stdout is never affected):
*** Update available: v0.5.0 — run `torrent_builder update` ***
The check is throttled to once per 24 hours (a timestamp is stored in
update_check.state under ~/.config/torrent-builder/ on Linux,
~/Library/Application Support/torrent-builder/ on macOS, and
%LOCALAPPDATA%\torrent-builder\ on Windows), so most runs make no network
request. Network errors are handled silently — it never blocks or crashes the
tool on offline.
Builds compiled from source without a git tag (reporting a dev version) get an
informational notice without the update command, since running
torrent_builder update would replace the locally-compiled binary with a
prebuilt release artifact:
*** Newer release available: v0.5.0 (you are running a dev build: dev (419271b)) ***
Disable the check for CI or offline environments:
- Set the
TB_NO_UPDATE_CHECK=1environment variable, or - Pass
--no-update-checkfor a single run.
The check only runs for the default creation flow; it is skipped for all
subcommands and when --quiet/--json is used.
-h, --help Show help
-v, --version Show version
--verbose Enable verbose output (conflicts with --quiet, --json)
-q, --quiet Suppress non-essential output, auto-decline prompts (conflicts with --verbose)
--json Output torrent metadata as JSON (implies --quiet, conflicts with --verbose)
-i, --interactive Run in interactive mode
-p, --path arg Path to file or directory (required)
-o, --output arg Output torrent file path (optional; auto-generated if omitted)
-t, --torrent-version arg Torrent version (1=v1, 2=v2, 3=hybrid) (default: 3)
--comment arg Torrent comment
-n, --name arg Set custom torrent name (overrides default inferred from path)
--private Make torrent private
--default-trackers Use default trackers
-T, --tracker arg Add tracker URL (can be used multiple times)
-w, --webseed arg Add web seed URL (can be used multiple times)
-s, --piece-size arg Piece size in KB (must be one of: 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768)
--target-piece-count N Target number of pieces (calculates optimal piece size; mutually exclusive with --piece-size)
--no-creator Omit creator field from torrent metadata
-d, --no-date Omit creation date from torrent metadata
--source arg Add source string to torrent info for cross-seeding
-e, --entropy Randomize info hash by adding entropy field
-x, --exclude arg Exclude files matching glob pattern (can be used multiple times)
-I, --include arg Include only files matching glob pattern (can be used multiple times)
--no-builtin-excludes Disable built-in system-file exclusions (.DS_Store, Thumbs.db, etc.)
--skip-prefix Omit tracker domain from auto-generated output filename
--output-dir DIR Directory for auto-generated output filename (created if needed)
--tracker-index N Index of tracker to use for filename prefix (0-based, default: 0)
--preset NAME Apply named preset from presets.yaml
--preset-file FILE Load presets from specified file (default: searches ./presets.yaml, $XDG_CONFIG_HOME/torrent-builder/presets.yaml, ~/.config/torrent-builder/presets.yaml)
--fail-on-season-warning Fail if a TV season pack has missing episodes
--no-update-check Skip automatic update check on startup
Note:
--verbose,--quiet, and--jsonare ignored in interactive mode. In CLI mode,--verboseand--quietare mutually exclusive, as are--verboseand--json. The--jsonflag implies--quietand auto-declines any overwrite prompts.
Piece size vs target piece count:
--piece-sizesets the exact piece size in KB.--target-piece-count Ncalculates the optimal power-of-2 piece size to approximate N pieces (common on private trackers like PTP/BTN/GGN). The actual count may differ slightly since piece sizes must be powers of 2. These two options are mutually exclusive. If both--target-piece-countand tracker rules (max_piece_length) are active, the target is resolved first and the rule logs a warning if the resolved size exceeds the limit (same behavior as explicit--piece-size).
When using --json, the output is a single JSON object to stdout (errors go to stderr):
{
"name": "filename",
"info_hash_v1": "...",
"info_hash_v2": "...",
"is_hybrid": false,
"total_size": 12345678,
"piece_length": 262144,
"piece_count": 48,
"files_count": 1,
"is_private": false,
"trackers": ["https://tracker.example/announce"],
"web_seeds": [],
"magnet_link": "...",
"output_path": "/path/to/output.torrent"
}Optional fields (comment, creation_date, created_by, source, entropy) appear only when present in the torrent metadata. Creator and creation date are included by default; use --no-creator and --no-date to omit them.
Note:
--versionnow shows the software version. For torrent format version, use--torrent-versionor-t.
./torrent_builder inspect <torrent_file> [options]
--json Output in JSON format
--files Show detailed file tree only
--verify Verify files exist on disk
--base-path DIR Base path for file verification (default: current directory)
./torrent_builder modify <torrent_file> [options]
-h, --help Show help
-t, --tracker URL Replace all trackers (exclusive with --add-tracker/--remove-tracker)
--add-tracker URL Add tracker URL (can be used multiple times)
--remove-tracker URL Remove tracker URL (can be used multiple times)
--private Mark torrent as private
--public Mark torrent as public
--source SOURCE Set source field (empty string removes it)
--comment COMMENT Set comment (empty string removes it)
--name NAME Change torrent name
--entropy Randomize info hash by adding entropy field
-o, --output OUTPUT Output torrent file path (defaults to in-place)
--dry-run Preview changes without writing
Note:
--trackeris exclusive with--add-tracker/--remove-tracker.--privateand--publicare mutually exclusive. At least one modification option is required.
Basic usage:
./torrent_builder -i
./torrent_builder --path /data/file --output file.torrent
./torrent_builder --path /data/file --output file.torrent --default-trackers
./torrent_builder --path /data/folder --output folder.torrent --torrent-version 2 --private
./torrent_builder --path /data/file --output file.torrent --piece-size 1024
./torrent_builder --path /data/movie.mkv --output movie.torrent --target-piece-count 600
./torrent_builder --versionAuto-naming (output filename generated automatically):
./torrent_builder --path /data/file --tracker "https://tracker.example.com/announce"
# Creates: tracker.example.com_file.torrent
./torrent_builder --path /data/file --tracker "https://tracker.example.com/announce" --skip-prefix
# Creates: file.torrent (no tracker domain prefix)
./torrent_builder --path /data/file --tracker "https://tracker.example.com/announce" --output-dir /torrents
# Creates: /torrents/tracker.example.com_file.torrent
./torrent_builder --path /data/file --tracker "https://tracker.example.com/announce" --output-dir /torrents/output
# Auto-creates /torrents/output if it doesn't existAuto-naming with multiple trackers:
./torrent_builder --path /data/file \
--tracker "https://alpha.tracker.io/announce" \
--tracker "https://beta.tracker.net/announce" \
--tracker-index 1
# Uses the second tracker for filename: beta.tracker.net_file.torrentCollision resolution (automatic when auto-naming):
# If tracker.example.com_file.torrent already exists:
./torrent_builder --path /data/file --tracker "https://tracker.example.com/announce"
# Creates: tracker.example.com_file(1).torrentAdd multiple trackers (added in ascending order of priority; the first tracker has the highest priority — tier 0):
./torrent_builder --path /data/file --output file.torrent \
--tracker udp://tracker.example.com:80 \
--tracker http://backup-tracker.org:6969Add multiple web seeds:
./torrent_builder --path /data/file --output file.torrent \
--webseed http://example.com/file \
--webseed http://mirror.com/fileCreate torrent with comment:
./torrent_builder --path /data/file --output file.torrent \
--comment "My important file"Cross-seeding (unique info hash per tracker):
./torrent_builder --path /data/file --output ptp.torrent \
--source "PTP" --tracker "https://ptp.example/announce"
./torrent_builder --path /data/file --output hdb.torrent \
--source "HDB" --tracker "https://hdb.example/announce"
./torrent_builder --path /data/file --output unique.torrent \
-e --tracker "https://tracker.example/announce"Omit creator and creation date for clean cross-seeding:
./torrent_builder --path /data/file --output clean.torrent \
--no-creator --no-date --tracker "https://tracker.example/announce"Season pack detection:
# Fail if the directory is an incomplete season pack (missing episodes)
./torrent_builder --path /data/Show.Name.S01 --output season.torrent \
--fail-on-season-warning
# Error: Season 1 pack has missing episodes (E03) in: Show.Name.S01
# Without the flag, the torrent is created normally
./torrent_builder --path /data/Show.Name.S01 --output season.torrentCreate a torrent with default trackers and custom trackers:
./torrent_builder --path /data/file --output file.torrent --default-trackers --tracker udp://mytracker.com:8080Exclude unwanted files from a directory:
./torrent_builder --path /data/folder --output folder.torrent \
--exclude "*.nfo" --exclude "*.txt"
./torrent_builder --path /data/folder --output folder.torrent \
--exclude "subs/**"Include only specific file types:
./torrent_builder --path /data/folder --output folder.torrent \
--include "*.mkv" --include "*.mp4"Note:
--includepatterns take precedence over--excludewhen both match. Glob syntax:*(any non-slash),**/(zero or more dirs),**(any path),?(single char). Matching is case-insensitive.
By default, common OS-generated metadata and junk files are excluded automatically (case-insensitive, matched at any depth):
| Pattern | Origin |
|---|---|
.DS_Store |
macOS Finder metadata |
Thumbs.db, desktop.ini |
Windows Explorer |
Zone.Identifier, Zone.Identifier:* |
Windows ADS (Mark-of-the-Web) |
@eaDir, @eaDir/** |
Synology NAS metadata |
*.torrent |
Avoid nesting existing torrent files |
Built-in excludes act as additional --exclude patterns, so --include still takes precedence — a file matching an --include pattern is kept even if it also matches a built-in. Disable with --no-builtin-excludes:
# System files excluded by default
torrent-builder /path/to/folder
# Opt out if needed
torrent-builder /path/to/folder --no-builtin-excludesVerbose, quiet, and JSON output:
./torrent_builder --path /data/file --output file.torrent --verbose
# Shows extra detail: file count, piece size reasoning, tracker tiers
./torrent_builder --path /data/file --output file.torrent --quiet
# Suppresses progress bar and summary; errors still shown
./torrent_builder --path /data/file --output file.torrent --json
# Outputs torrent metadata as JSON to stdout (useful for scripting)Inspect torrent metadata:
./torrent_builder inspect file.torrent
# Shows: name, info hash (v1/v2), size, piece size, trackers, web seeds, comment, magnet link
./torrent_builder inspect file.torrent --json
# Same info in JSON format (useful for scripting)
./torrent_builder inspect file.torrent --files
# Shows detailed file tree with sizes
./torrent_builder inspect file.torrent --verify --base-path /data
# Verifies all files exist on disk under /dataModify torrent metadata:
./torrent_builder modify file.torrent --tracker "https://tracker.example/announce"
# Replaces all trackers with the specified one
./torrent_builder modify file.torrent --add-tracker "https://tracker2.example/announce"
# Adds a tracker to the existing list
./torrent_builder modify file.torrent --remove-tracker "https://old.example/announce"
# Removes a specific tracker
./torrent_builder modify file.torrent --private
# Marks torrent as private
./torrent_builder modify file.torrent --public
# Marks torrent as public (removes private flag)
./torrent_builder modify file.torrent --source "PTP"
# Sets source field for cross-seeding
./torrent_builder modify file.torrent --source ""
# Removes source field
./torrent_builder modify file.torrent --comment "Updated comment"
# Sets or updates comment
./torrent_builder modify file.torrent --comment ""
# Removes comment
./torrent_builder modify file.torrent --name "New Name" --entropy
# Changes torrent name and randomizes info hash
./torrent_builder modify file.torrent --dry-run --tracker "https://tracker.example/announce"
# Preview changes without writing to file
./torrent_builder modify file.torrent --output modified.torrent --entropy
# Write to a new file instead of modifying in-placePresets save per-tracker settings in a YAML file. Use --preset <name> to apply a preset when creating a torrent.
Preset file format (presets.yaml):
version: 1
default:
private: true
exclude_patterns: ["*.nfo", "*.txt"]
presets:
ptp:
source: "PTP"
trackers:
- "https://ptp.example/announce"
exclude_patterns: ["*.nfo", "*.txt", "*.sfv"]
target_piece_count: 1000
public:
private: false
trackers:
- "udp://tracker.example/announce"
cross-seed:
no_creator: true
no_date: true
trackers:
- "https://tracker.example/announce"
builtin_excludes: false # disable system-file exclusions for this presetNote:
builtin_excludes(default:true) controls the automatic exclusion of.DS_Store,Thumbs.db, and other system files. Set it tofalseto disable. See Built-in system-file exclusions.
Preset file resolution: --preset-file (if given, used directly). Otherwise, search order: ./presets.yaml → $XDG_CONFIG_HOME/torrent-builder/presets.yaml → ~/.config/torrent-builder/presets.yaml.
Merge hierarchy: CLI flags > preset values > default: section > built-in defaults.
Usage:
# Apply a preset
./torrent_builder --preset ptp --path /data/file -o file.torrent
# Specify a custom preset file
./torrent_builder --preset ptp --preset-file /config/presets.yaml --path /data/file -o file.torrent
# Preset values are overridden by CLI flags
./torrent_builder --preset ptp --path /data/file -o file.torrent --comment "override"Create multiple torrents in parallel from a YAML config file.
Batch file format (batch.yaml):
version: 1
workers: 2
preset_file: presets.yaml
output_dir: /torrents/output
jobs:
- path: /data/movie1.mkv
preset: ptp
- path: /data/movie2.mkv
output: custom_output.torrent
target_piece_count: 600
trackers:
- "https://tracker.example/announce"
- path: /data/Show.Name.S01
fail_on_season_warning: true
- path: /data/cross_seed.mkv
no_creator: true
no_date: true
- path: /data/full_dump
builtin_excludes: false # include system files (e.g. for a raw backup)Note: Output paths automatically receive a
.torrentextension if not already present.workers: 0in the YAML config throws an error;--workers 0on the CLI is ignored with a warning.
Usage:
# Run a batch job
./torrent_builder batch batch.yaml
# Override worker count
./torrent_builder batch batch.yaml --workers 4Each job can optionally reference a preset by name. Jobs run in parallel with --workers threads (default: 1). A summary showing success/failure per job is printed at the end.
- Compilation Error: 'contains' is not a member of 'std::ranges': This occurs with older compilers (e.g., GCC 12 on Debian 12). CMakeLists.txt requires GCC 13+ for C++23. Solutions:
- Upgrade GCC:
sudo apt install g++-13(via backports on Debian 12) or upgrade to Debian 13/Ubuntu 24.04. - Use Docker for testing:
docker run -v $(pwd):/app -w /app ubuntu:24.04 bash -c "apt update && apt install -y build-essential cmake libtorrent-rasterbar-dev pkg-config && mkdir build && cd build && cmake .. && make".
- Upgrade GCC:
- libtorrent Not Found or pkg-config Error: Check your installation:
pkg-config --modversion libtorrent-rasterbar. Reinstall if < 2.0.10 (e.g.,sudo apt install libtorrent-rasterbar-dev pkg-config). pkg-config is required for dependency detection. - FetchContent/cxxopts Failure: Make sure you have an internet connection (it downloads the library during the configure step).
- Need More Help: Open a GitHub issue with logs (e.g.,
cmake .. 2>&1 | tee cmake.logandmake 2>&1 | tee make.log).
This project is licensed under the MIT License - see the LICENSE file for details.