Thanks for your interest in improving HYDRA! Contributions of all kinds are welcome — bug reports, feature requests, documentation fixes, and code.
- Project Layout
- Prerequisites
- Building
- Before You Submit
- Testing
- Commit Messages
- Pull Request Process
- Reporting Bugs
- Licensing of Contributions
HYDRA is a Cargo workspace with twelve crates:
| Crate directory | Published as | What it is |
|---|---|---|
crates/hydra-core |
hya-core |
I/O-free download scheduler: range partitioning, range stealing, collapse/stall detection |
crates/hydra-net |
hya-net |
Transport layer: HTTP/1.1, HTTPS (rustls), FTP, HTTP CONNECT, SOCKS proxies |
crates/hydra-ffi |
libhydra |
Stable C ABI over the engine, for embedding in other languages and on mobile |
crates/hydra-cli |
hydra binary |
The CLI, wget/curl compatibility dialects, and the interactive TUI |
crates/hydra-gui |
— | Cross-platform desktop download manager (iced) |
crates/hydra-host |
— | Native-messaging host bridging browser extensions to the app |
crates/hydra-stream |
hya-stream |
HLS/DASH manifests and segment assembly |
crates/hydra-updater |
— | Shared updater and update finisher |
crates/hydra-plugin-api |
hya-plugin-api |
Plugin manifests, plans, forms, permissions and ABI contract |
crates/hydra-plugin-sdk |
hya-plugin-sdk |
Rust guest SDK for Wasm plugin authors |
crates/hydra-plugin |
hya-plugin |
Embeddable Wasm host, package verification and plugin manager |
crates/hydra-plugin-cli |
hya-plugin-cli |
hydra-plugin authoring CLI: interactive init, build, validate and pack |
Browser extensions live in extensions/ (chrome/, firefox/, safari/), packaging and release tooling in scripts/ and the Makefile, and design docs in docs/.
A good rule of thumb for where a change belongs: scheduling logic goes in hydra-core (it must stay free of I/O), protocol/transport work in hydra-net, and user-facing behavior in hydra-cli or hydra-gui.
-
Rust 1.86+ (the workspace pins the
stablechannel viarust-toolchain.toml, which also pulls inrustfmtandclippyautomatically). -
Linux only — GUI/system dependencies used by CI and the desktop build:
sudo apt-get install -y pkg-config libasound2-dev libx11-dev libxrandr-dev libxcb1-dev libxkbcommon-dev
-
macOS / Windows — no extra system dependencies for a standard build.
# CLI only
cargo build --release # binary at target/release/hydra
# Everything (CLI + GUI + native-messaging host)
make buildOther useful Makefile targets: make cli, make gui, make host, make ffi (the embeddable libhydra plus its header), and platform packaging targets (make dmg on macOS, make deb / make rpm on Linux, make windows).
CI enforces all of the following, so running them locally saves a round trip:
# 1. Formatting (CI fails on any diff)
cargo fmt --all -- --check
# 2. Lints (warnings are errors in CI)
cargo clippy --all-targets --all-features -- -D warnings
# 3. Tests, debug and release (CI runs both)
cargo test --all-targets --all-features
cargo test --release --all-targets --all-featuresIf you touched crates/hydra-ffi, four more:
# 4. include/hydra.h is generated and committed; CI fails if it drifted.
# Needs cbindgen: cargo install cbindgen --locked
make header-check
# 5. Whether the change was ALLOWED. Every enumerator value, field offset,
# struct size and exported symbol in ABI 1 is frozen; additions the
# contract permits pass, movements do not. See docs/ffi/ABI.md.
make ffi-compat
# 6. The checks no Rust test can perform: a C compiler accepting the header,
# the two sides agreeing on struct layout, every promised symbol present,
# and every header this project has ever published still working against
# the library built from your branch. Also compiles the header alone as
# C99/C11/C17 and C++11/C++17.
make ffi-test
# 7. If you changed the packaging, the release archive still builds.
# This is the same script the release workflow runs.
make ffi-distThe ABI is a promise, not a preference. docs/ffi/ABI.md
is the specification: read section 3 before changing anything in
crates/hydra-ffi/src/abi.rs. In short — within ABI 1, fields never move and
never change width or meaning, enumerator values are never reassigned, symbols
never disappear, and new fields may only be appended to the two size-prefixed
configuration structs. Anything else needs HYDRA_FFI_ABI_VERSION = 2, not an
edit to crates/hydra-ffi/abi/abi-1.manifest. That file is regenerated with
scripts/ffi-abi-compat.sh --update only when appending within the rules or
starting a new ABI version — never to make a failing check pass.
libhydra is released for Linux (glibc and musl), macOS, Windows, Android and
iOS. The per-platform integration guides are in docs/ffi/ and are
copied into every release archive, so a change to the ABI usually means a change
to one of them too.
-
Put unit tests next to the code they cover; integration tests go in each crate's
tests/directory. -
New engine behavior in
hydra-coreshould come with tests — the scheduler is deliberately I/O-free precisely so it can be tested deterministically without a network. -
Anything added to the C ABI needs a test in
crates/hydra-ffi/tests/abi.rs, which calls the exported symbols the way a C program does. Reaching into the crate's internals from there defeats the purpose: the point is evidence that the interface works. If the change alters the header, add a check toexamples/ffi-c/abi_smoke.cas well — struct-layout and linkage faults are invisible to Rust tests by construction.examples/ffi-c/compat_probe.cis the other side of that: it is compiled against every published header rather than the current one, so it may only use the ABI 1 surface that has existed since ABI 1 was published. -
Coverage is tracked on Codecov. A PR doesn't need to hit a specific number, but changes that add meaningful logic without any tests will usually get pushback.
-
To reproduce the coverage report locally:
cargo llvm-cov --workspace --all-features --ignore-filename-regex '(/examples/|/benches/)'
HYDRA follows Conventional Commits:
<type>(<optional scope>): <short summary>
Types in use: feat, fix, docs, chore, refactor, test, perf, ci. Scope is the crate or area touched, e.g.:
feat(cli): add --sort-by-type category sorting
fix(net): handle FTP REST beyond 2 GiB
chore(extensions): bump browser extension manifests to 0.2.2
Keep the summary imperative and under ~72 characters. Branch names follow the same spirit: feat/short-description, fix/short-description.
- Fork the repository and create a branch off
main. - Make your change, including tests and doc updates where relevant.
- Run the pre-submit checks locally.
- Open a PR against
maindescribing what changed and why. Link the related issue if one exists. - CI (formatting, clippy, tests, coverage) must pass before review/merge.
For large features or anything that changes engine behavior (scheduling, stall detection, integrity), please open an issue first to discuss the design — it avoids wasted work on both sides.
Open an issue at github.com/ja7ad/hydra/issues with:
- HYDRA version (
hydra --version), OS, and how it was installed (installer script, package, source). - The exact command line (redact URLs/credentials as needed) and what happened vs. what you expected.
- For engine issues: whether the server supports ranges, number of connections/mirrors, and any proxy in the path.
For security vulnerabilities, please do not open a public issue — report them privately via GitHub security advisories.
HYDRA uses a split licensing model (see LICENSING.md):
- Contributions to
crates/hydra-core,crates/hydra-net,crates/hydra-ffi,crates/hydra-plugin-api,crates/hydra-plugin-sdk,crates/hydra-pluginandcrates/hydra-plugin-cliare accepted under MIT OR Apache-2.0 (dual license).crates/hydra-ffimust never gain a dependency onhydra-cli,hydra-guiorhydra-host: those are GPL, and Rust links statically, so one such dependency would relicense the embeddable library by accident. - Contributions to
crates/hydra-cli(and the rest of the workspace) are accepted under GPL-3.0-or-later.
By submitting a pull request, you agree that your contribution is licensed under the license(s) of the crate(s) it modifies. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion shall be licensed as above, without any additional terms or conditions (per Apache-2.0 §5 for the dual-licensed crates).