sabrصبر

for slow, throttled and unreliable connections

Downloads that
never start over.

git clone, docker pull and big downloads are all-or-nothing: one dropped connection at 97% and you start again from zero. sabr splits them into small, resumable steps, so a drop costs a few seconds instead of the whole download. It even survives a reboot.

curl -fsSL https://mrzroot.github.io/sabr/install.sh | sh

The installer is resumable too, and it checks SHA-256. Single static binary; only needs git (for clone) and nothing else.

git clone→sabr clone
docker pull→sabr docker pull --load
curl -O→sabr get --sha256

Race them on a bad link

An interactive simulation of how each tool behaves on a link that drops. The real run, with real numbers, is further down.

Simulation
git clone
0%

    
sabr clone
0%

    

Time is sped up. Each tool's behaviour is simplified: git restarts the pack from zero after a drop; sabr loses only the step in flight, retries with backoff and halves the step size.

How sabr clone works

  1. 1

    Latest commit

    A blobless, depth-1 fetch: just commits and folders, a few hundred KB.

  2. 2

    History, in steps

    It deepens history step by step. The step size doubles after a success and halves after a drop.

  3. 3

    Files, in batches

    It lists the missing blobs and fetches them in adaptive batches. Any file that keeps failing is downloaded by byte range and hash-checked.

  4. 4

    A normal repo

    Then it checks out, sets the upstream and origin/HEAD, and you have the same result as git clone. Progress is saved in .git/sabr.json, so a kill or reboot just resumes.

sabr docker pull

Talks to the registry directly, resumes each layer from the byte it stopped at, and keeps a shared layer cache. It writes a docker load archive; add --load to load it into Docker or Podman. No daemon changes.

$ sabr docker pull python:3.12-slim --load
  ✓ 41.3 MiB, 39 resumes

sabr get

Byte-range resume across runs. It restarts if the file changed on the server, has a stall watchdog, and verifies SHA-256.

$ sabr get https://nodejs.org/…/node.tar.xz \
    --sha256 3b1c…

sabr chaos

A built-in bad link: a local proxy that cuts or freezes every connection after N bytes. Use it to test your own tools.

$ sabr chaos --listen 127.0.0.1:8899 --cut 2MB

A real run, not a simulation

GitHub's cli/cli (12,357 commits) through a proxy that cuts every connection after about 2 MB. The same test runs in CI on every push.

$ git -c http.proxy=http://127.0.0.1:8899 clone https://github.com/cli/cli
fatal: early EOF
fatal: fetch-pack: invalid index-pack output              ← back to 0%, every time

$ HTTPS_PROXY=http://127.0.0.1:8899 sabr clone https://github.com/cli/cli
==> Fetching history in resumable steps (commits and folders only)
    +64 commits (65 so far)
  ! step of 128 commits failed (early EOF); next try 64 commits in 985ms
    …
==> Fetching files of the latest commit: 1506 to go
    256/1506 files (16%)
  ! batch of 512 files failed (early EOF); next batch 128 files in 927ms
    …
==> Checking out trunk
  ✓ done: cli (49s, 27 steps, 17 drops survived, 14.0 MiB received)
survives a dropsurvives kill/rebootautomaticgit historydocker imagesingle file
git clone✗✗–✓
git backfill (2.49+)old blobs onlyold blobs only✓needs a finished blobless clone
SO sparse-checkout scriptfiles onlyfiles only~metadata is still one shot
docker pull✗✗–✓
containerd snapshotter✓✓✓✓ daemon config change
wget -c / aria2✓✓✓✓
sabr✓✓✓✓✓ any machine✓