Releases: InfoDiveLabs/braid
Release list
Braid 0.1.0
Braid splits one download across every network path you have — Wi-Fi, Ethernet, and a phone's mobile data at the same time — verifies every chunk, and survives links that expire mid-transfer.
This is the first release that is not a beta.
New: run it on a server
braid-server is the same engine with no window: a container, a web UI, and an API.
services:
braid:
image: ghcr.io/infodivelabs/braid:0.1.0
ports: ["8080:8080", "6881:6881", "6881:6881/udp"]
volumes: ["./config:/config", "./downloads:/downloads"]
environment: [PUID=1000, PGID=1000]It answers qBittorrent's API, so Sonarr, Radarr, Prowlarr and Lidarr drive it by changing the host, port and password on the qBittorrent client they already have. Verified against a real Sonarr 4.0.20 and Radarr 6.4.4, from grab to library import, with those exchanges replaying as tests.
It exists because a media stack usually runs a torrent client and something else for direct downloads, and the something else is a shell script with curl in it — no resume, no integrity check.
Also in the container: multi-interface downloads, per-torrent folders and tags, categories that survive a restart, and password changes from the Settings page. Migration steps are in docker/README.md.
Desktop
| Platform | File | Notes |
|---|---|---|
| macOS 11+ | Braid-0.1.0-macos.dmg |
Unsigned: first launch needs right-click, then Open |
| Debian, Ubuntu | braid_0.1.0_amd64.deb |
sudo apt install ./braid_*.deb |
| Fedora, RHEL | braid-0.1.0.x86_64.rpm |
sudo dnf install ./braid-*.rpm |
| Windows 10+ | braid-0.1.0.msi |
Multi-NIC is unverified on hardware |
Pair an Android phone to add its mobile data as an extra lane: braid-android-0.1.1.apk, checked on a Pixel 7 Pro against a real carrier.
Known limitations
- Windows multi-NIC is unverified.
IP_UNICAST_IFis implemented from Microsoft's documentation with no Windows hardware to confirm it. Everything else on Windows is unaffected. The Network settings page shows the binding mechanism actually in force, so a silent fall back is visible. - Nothing is code signed. macOS and Windows will both warn.
- The server's qBittorrent API covers what the
*arrapps ask for, not everything qBittorrent documents. A generic client or mobile app will find trackers, peers, per-file priority, recheck and rename missing. Tracked in #12. - Seed and leecher counts read zero in the server's API.
Braid 0.1.0-beta.3
Downloads are substantially faster in this release, on ordinary links, for an
unglamorous reason: a connection used to ask the origin for one chunk, wait,
and ask for the next. Between every pair of requests was a round trip doing
nothing. Measured against a real CDN that came to more than half the available
bandwidth.
A connection now takes a contiguous stretch of the file and streams the whole
thing in a single request, cutting chunks out of the body as the bytes pass.
Chunks are still exactly what they were to the journal and the per-chunk hash,
which is what keeps corruption local and a crash cheap. They simply no longer
each cost a request.
Twenty-five one-second samples against releases.ubuntu.com:
| mean | range | |
|---|---|---|
| beta 2 | 7.8 MB/s | 1 to 24 |
| beta 3 | 33.1 MB/s | 9 to 55 |
It also reaches full speed in about three seconds rather than crawling for
fifteen.
A slow path no longer decides when a download finishes
Borrowing a phone's mobile data is the point of this project, and until now a
path much slower than the others could cost more than it contributed: whatever
it was carrying when everything else ran out set the finish time.
Three things were wrong. A stretch down to its last chunk could not be handed
over, so a gigabit card waited on a phone. A chunk already in flight could not
be handed over at all. And a chunk only checked whether it had been called off
when bytes arrived, which tied how fast it could stop to how fast it was going,
so the slowest path was the slowest to notice.
A faster lane can now take over a single remaining chunk, or fetch its own copy
of one a slower lane is carrying and keep whichever lands first. Only a lane at
least half again as fast may do that, and only two lanes per chunk, because a
duplicate over mobile data is somebody's money. Measured on a path sixty times
slower than its neighbour: it used to cost 2.43s on a 2.87s download, and now
costs nothing at all.
Each lane works out how many connections it is worth
Opening eight connections to everything is wrong in both directions. One
connection to a distant origin is held back by its own window rather than by
the link; a phone sharing mobile data is often saturated by two, and the other
six spend its battery carrying nothing.
Each lane now starts with one connection and doubles while doubling measurably
helps, then settles on whichever count was fastest. The connections setting is
a ceiling for one lane rather than a total for the transfer.
Phones
- A phone that stops sharing and starts again is picked up within a few
seconds. Before this it stayed dead for the rest of the transfer, because the
path was remembered as familiar rather than checked for whether it was still
carrying anything. - A paired phone is followed when its address changes. Addresses are leases,
and either end rejoining its Wi-Fi is enough to change one. Matching is on the
device's identity, never its name: two people on one network calling their
phone by its model name is not a rare accident. - A lane that appears mid-download now joins that download, rather than waiting
for the next one. dl --relaylets the command line use a phone, which only the desktop app
could do before.
Reading the numbers
- Sizes and speeds are in MB and GB throughout, decimal, matching what a
download page and the Finder quote. The binary spellings are still accepted
wherever you can type a size. - The speed shown is a plain mean over the last second, so it settles instead
of chasing. It used to be an exponential average, which followed every swing
of a link that genuinely varies. - The sidebar meters use a speed test's scale, compressing as they go right.
Drawn proportionally, a phone on mobile data beside a fast card is half a
percent of the bar and indistinguishable from an interface doing nothing,
which is the one distinction the sidebar exists to make.
Installing
| macOS (Intel and Apple silicon) | Braid-0.1.0-macos.dmg |
| Windows x86-64 | braid-0.1.0-x86_64.msi |
| Windows on ARM | braid-0.1.0-aarch64.msi |
| Debian and Ubuntu, x86-64 | braid_0.1.0-1_amd64.deb |
| Debian and Ubuntu, ARM64 | braid_0.1.0-1_arm64.deb |
| Fedora and RHEL, x86-64 | braid-0.1.0-1.x86_64.rpm |
| Fedora and RHEL, ARM64 | braid-0.1.0-1.aarch64.rpm |
The Android companion is at
InfoDiveLabs/braid-android.
Nothing here is code signed. macOS will refuse the first launch: open it
from the right-click menu, or allow it in Privacy and Security. Windows
SmartScreen will warn.
macOS asks for local network access the first time you look for a phone. It
has to be allowed or the desktop cannot reach one at all, and the failure looks
exactly like the phone not being there. It cost us an afternoon; it is worth
your thirty seconds.
What is not verified
- The Windows packages have never been installed by anyone. There is no Windows
hardware here. - Windows interface binding is written from Microsoft's documentation and has
no test job on ARM. - The phone path has no throughput measurement on real hardware. The fixes
in this release have tests, and the companion was confirmed reachable and
serving, but no end-to-end number was taken through a phone. - A phone shared over Wi-Fi sends every byte across the air twice: once from the
phone to the router, once from the router to you. When Wi-Fi rather than your
internet connection is the limit, it adds little. A USB tether avoids this
entirely. - Everything measured here was measured on one Mac, on one connection, in India.
Braid 0.1.0-beta.2
Braid splits one download across every network path you have, and from this beta that
includes a phone's mobile data. Wi-Fi, Ethernet and a paired phone pull the same file
at once, reassembled exactly.
New: phones as download paths
Pair an Android phone and each network it offers becomes its own path, weighted
independently against your own cards.
- Pairing is a code on screen. Press Add phone in the sidebar, then Show
code, and point the phone at it. Nothing typed, and nothing that depends on
multicast surviving your network. - The phone decides what it lends and how much data it will spend. Switch mobile
sharing on there and the path appears here by itself. Braid displays what it is told
and enforces nothing of its own. - A phone that sleeps, runs out of allowance or walks out of range costs its own
path and never the file. Its work moves to the paths that remain. - A path that is your own connection wearing a second name is detected by comparing
the address each one leaves from, and shown switched off with that reason rather than
counted twice.
The companion is Braid for Android,
released separately as a signed APK.
Fixed since beta 1
- Pausing kept spending mobile data. Cancellation was checked only between chunks,
so a pause left every chunk in flight running to the end on every path at once. - A relay that refused us failed the whole download instead of costing that one
path. - Progress could step backwards after a retry.
- Path throughput was only recalculated when a chunk completed, so a slow path
reported a figure minutes old and the scheduler weighted it on that. - Byte figures were binary arithmetic wearing decimal labels. They are KiB, MiB and
GiB now, which is what the arithmetic always was. No number changed, only its name. - The Inspector drew its piece grid on two tabs and rebuilt it ten times a second,
which made the window sluggish whenever it was open. - Interfaces appearing after launch, a tether or a cable, were never noticed until
the application restarted.
Which file
| Platform | Download |
|---|---|
| macOS, Apple silicon and Intel | Braid-0.1.0-macos.dmg (one universal build) |
| Windows x86_64 | braid-0.1.0-x86_64.msi |
| Windows on ARM | braid-0.1.0-aarch64.msi |
| Debian, Ubuntu x86_64 | braid_0.1.0-1_amd64.deb |
| Debian, Ubuntu ARM64 | braid_0.1.0-1_arm64.deb |
| Fedora, RHEL x86_64 | braid-0.1.0-1.x86_64.rpm |
| Fedora, RHEL ARM64 | braid-0.1.0-1.aarch64.rpm |
| Android 8+ | braid-android |
Every package installs the application (braid) and the command line tool (dl).
Before you install
Nothing here is code signed. macOS will refuse to open the app on a double click:
right click it, choose Open, and confirm once. Windows SmartScreen will warn for the
same reason. If that is not acceptable, build from source.
macOS will ask for local network access the first time you look for a phone.
Without it the desktop cannot reach one at all, and the failure looks like the phone
not being there.
Known limitations
Braid is developed on a Mac. The Windows and Linux builds pass the full test suite
in CI on every push, but nobody has sat in front of those desktops and used the
application.
- Nobody has installed the Windows packages. CI builds them and WiX accepts them,
which proves they compile and link and nothing more. - Windows interface binding is written from Microsoft's documentation, not from
experiment.IP_UNICAST_IFfollows the docs and the app reports the mechanism
actually in force, but no machine with two live NICs has run it. - Windows on ARM is built and packaged, and has no test job.
- A torrent uses one interface at a time. Its peer connections could be spread
across several, and are not yet. - Cross-application drag and drop does not work on any platform. Links arrive
through the system handler, the clipboard or the command line. - A camera has read the pairing code on one phone model. If yours will not scan it,
the address is printed under the code and can be typed.
Reporting something
Open an issue with the platform, the kind of transfer, and what the Inspector showed.
If a file came out wrong, say so first and loudly: that is the one bug class this
project exists to not have.
Braid 0.1.0-beta.1
Braid splits one download across every network path you have: Wi-Fi, Ethernet and a
tethered phone pulling the same file at once, reassembled exactly. It also speaks
BitTorrent, survives a crash mid-transfer, and re-resolves expiring links before they
lapse rather than after they fail.
This is the first beta. It is feature complete for what it claims to do, and it was
built on a Mac: the Windows and Linux builds have been tested by CI rather than by
anyone using them. Read the limitations before trusting it with something you cannot
download again.
Which file
| Platform | Download |
|---|---|
| macOS, Apple silicon and Intel | Braid-0.1.0-macos.dmg (one universal build) |
| Windows x86_64 | braid-0.1.0-x86_64.msi |
| Windows on ARM | braid-0.1.0-aarch64.msi |
| Debian, Ubuntu x86_64 | braid_0.1.0-1_amd64.deb |
| Debian, Ubuntu ARM64 | braid_0.1.0-1_arm64.deb |
| Fedora, RHEL x86_64 | braid-0.1.0-1.x86_64.rpm |
| Fedora, RHEL ARM64 | braid-0.1.0-1.aarch64.rpm |
Every package installs the braid application and the dl command line tool.
What is in it
- Multi-path downloads. Each connection is bound to a chosen interface rather than
left to the routing table. Slow links get fewer chunks, a link that dies has its work
migrated, and a capped interface is a ceiling rather than a suggestion. - Crash-safe storage. Chunk data is made durable before the journal claims it, in
every durability mode. A crash costs the bytes in flight, never the file. - Per-chunk verification. BLAKE3 as each chunk lands, so corruption is localised and
re-fetched rather than restarting the transfer. Whole-file checks in BLAKE3, SHA-256
or MD5. - Refusal to produce a wrong file quietly. A server that advertises
Rangeand
ignores it, a200where a206was asked for, a non-identity encoding on a ranged
response, a login page with a plausibleContent-Length: all caught rather than
written to disk. - BitTorrent. Magnet links and
.torrentfiles in the same list as everything else,
with per-file progress, peers, seeding, and the same limits and schedule. A client,
not an index: no search, no bundled tracker list. - Expiring links re-resolved proactively and once, not once per connection.
- Transfers survive quitting. Each row returns in the state it was left in, and an
unfinished one resumes from its journal rather than starting again.
Binary size is 15.5 MB on macOS and 23.4 MB on Linux x86_64.
Before you install
Nothing here is code signed. macOS will refuse to open the app on a double click:
right click it, choose Open, and confirm once. Windows SmartScreen will warn for the
same reason. If that is not acceptable to you, build from source instead.
Known limitations
Braid is developed on a Mac. There is no Windows or Linux machine here, so
everything on those platforms has been exercised through CI and containers rather than
by a person using it. CI runs the full test suite on Windows x86_64 and on Linux, and
it passes. What has not happened is someone sitting in front of a Windows desktop and
using the application.
Concretely:
- Nobody has installed the Windows packages. CI builds them and WiX accepts the
definition, which proves they compile and link and nothing more. Treat a first
install as untried, and please say what happens. - Windows interface binding is written from documentation, not from experiment.
IP_UNICAST_IFfollows Microsoft's docs and the app reports the binding mechanism
actually in force rather than the one requested, but no machine with two live NICs
has ever run it. Single-interface downloads, storage and the UI are unaffected. - Windows on ARM has no test job. It is built and packaged; the suite runs on
Windows x86_64 only. - Linux is tested, but only by machines. The suite runs in CI on x86_64 and ARM64
and in a container locally. No one has used the desktop application on a Linux
desktop. - A torrent uses one interface at a time. Outgoing peer connections could be spread
across paths, and are not yet; the session binds to a single interface. - Cross-application drag and drop does not work on any platform. Links arrive
through the system handler, the clipboard or the command line. - A torrent re-checks on resume. The session is not persisted, so a torrent resumed
in a new process verifies what is on disk before continuing. Correct, and slower than
it needs to be.
Reporting something
Open an issue with the platform, the transfer kind, and what the Inspector showed. If a
file came out wrong, say so first and loudly: that is the one bug class this project
exists to not have.