Repository navigation
0.16.0 - 2026-11-07
bb 0.16.0: parallel chunk uploads for bb push, bb backup for Linux, live transfer numbers, and folder pushes you can safely repeat
bb push now sends up to 4 chunks of a file at once (--parallel N, from 1 to 8). bb backup backs up folders from a Linux machine into your Backups folder, and the CLI now protects that folder: bb push, bb mv, bb mkdir and bb rm follow the same rule the server enforces. bb push now shows what a transfer is doing while it runs: the current speed in Mbps, the time left, and, with -v, how many chunks are done and in flight and which storage country the file goes to (Germany or Finland). Pushing a folder is also safe to repeat. A second push of the same folder reuses the folder that is already there instead of making another one with the same name, skips the files this machine already uploaded unchanged, and an interrupted upload finishes in the folder you asked for, not in the one an earlier run was using.
What's New
-
bb pushsends up to 4 chunks of a file at once.--parallel Nsets how many, from 1 to 8; the default is 4. Every chunk buffer is charged to one 640 MiB upload buffer before it is allocated, so no setting makes a push hold more memory than 0.15.0's one-chunk-at-a-time push did at its worst moment (640 MiB); the default holds up to 512 MiB. Files over 2 GiB use smaller chunks as N rises, 64 MiB at 4 and 32 MiB at 8. A file whose chunks don't fit the buffer gets fewer at once, and-vsays so:<name>: 2 chunks at once, not 8: its 128 MiB chunks fill the 640 MiB upload buffer. The-vstats line shows<in flight>/<used> in flight. A rate limit (429) or a busy storage pool (503) now pauses the whole push once, with one notice, instead of each chunk on its own. Ctrl-C stops the whole push, a folder push included: the chunks in flight are dropped and the upload stays resumable, the push printsInterrupted: k of n chunks of <name> confirmed in this run. Run the same command to continue.and exits 130, and a second Ctrl-C exits at once. Running the same command again continues the upload, and chunks the server already has are skipped.--json: thetransferobject gainsparallel_askedandpauses. -
bb backupbacks up folders from a Linux machine.bb backupworks on Linux only for now. On macOS and Windows,bb backup runrefuses: it needs the Linux machine id. The commands arebb backup add <folder>,remove,list,runandstatus.bb backup runmakes one pass over every folder you added: new and changed files are encrypted on your machine, exactly as forbb push, and uploaded into a folder for this machine inside Backups. A changed file becomes a new version of the same file, and a file that vanished and comes back is uploaded as a new file. Files are read in place. A file that changes while it uploads is not completed, so a copy that is half old and half new never lands.addrefuses a folder inside bb's own state folder, abb syncfolder or a mount, and folders that overlap one you already added.bb backup runprints counts and folder names, never file names or paths, so it is safe to leave its output in a journal. The README has a systemd user timer (service, timer, linger) that runs it every hour. -
Exit codes for
bb backup runandstatus: 0 when everything is done; 3 when the run finished but something was not done (a file that failed, or the device's manifest that could not be written; the next run tries again); 4 when a folder was turned off because its backup was deleted elsewhere. A turned-off folder is never uploaded again by itself:bb backup add <folder>backs it up again, from scratch. A secondbb backupwhile one is running exits 75. -
Backups are protected on both sides:
bb pushwon't add files inside Backups, the Backups folder itself can't be renamed, moved or deleted, and the server refuses the same changes. Deleting a device's backup withbb rmalways asks first, with the item count; only--yesanswers that question.bb mvandbb mkdirfollow the same rule. A refused write says why and points tobb backup add <folder>.bb lsmarks the Backups folder[Read-only](--jsongainsbadgeandsystem_role) and never lists the per-device manifest file. -
Live numbers while
bb pushruns. On a terminal you get one line that moves each time the server confirms a chunk: a bar, bytes done of the total, the current speed in Mbps, and the time left. The current speed is measured over a window of at least 10 seconds, and the time left counts down between chunks. Until the first chunk is confirmed, speed and time left show a dash. Speeds are decimal megabits per second, to one decimal.bb speedtestnow prints its speeds the same way. The average and the total time in the summary leave out the time you spent answering a conflict prompt, because that wait is not transfer time; they still include the gaps between files (the name check, starting the upload, finishing it). -
-v/--verboseforbb push. Adds the chunks done of the total, how many are in flight, the average speed, the storage country the file goes to (Germany or Finland; nothing is printed when the server does not name one), how many chunks went directly to object storage and how many through the API, and how many were retried. It also prints one line per chunk and a detail line under the summary.-vbelongs tobb pushonly for now. With--quietit is a usage error (exit 2); with--jsonit has no effect. -
Clearer end lines. The finished line shows a duration such as
7m 21sinstead of raw milliseconds, says1 fileinstead of1 files, and no longer runs the file name into its size. Long names are shortened in the middle to fit the terminal width. On a pipe or with stderr redirected there are no live lines; with-vthe per-chunk lines and the end lines still print. -
bb push --jsonreports atransferobject with the run's totals (bytes, chunks, average speed inavg_mbps,duration_ms, the direct and API chunk counts, retries) and apoolslist that names the storage country only:country,country_codeandchunks, never a pool id. It is additive: nothing that was there changes, and the existing top-leveltotal_duration_msis still the wall time of the whole run. -
Pushing a folder again reuses its folder.
bb push <folder>andbb push --folder <name>look for a folder of the same name at every level and reuse it, instead of creating a second one. A name matches only when it decrypts to exactly the same bytes. If several folders have the same name, the oldest folder that is not shared wins, and a line says how many there are. -
A folder that is shared is not reused silently. If the folder you are pushing into already exists and is shared with people or through links,
bb pushasks first at a terminal (the default is No, and the question says how many people and links). With no terminal,--jsonor--quietit refuses with exit 2. The new--reuse-sharedflag uploads into it without asking. Answering No makes a new folder, and later runs keep using it. With--folder, a shared folder is used only when every folder of that name is shared, and the push says so. -
A re-push skips what was already uploaded. A file is skipped, and counted as
skipped N already uploaded(total_already_uploadedin--json), only when this machine's own record shows it uploaded that file into this folder (same path, size and modification time) and the server still holds it there, finished at that version and at that size. Anything else is treated as before: a changed file, a newer version, a file another machine pushed or a file that was moved or trashed. This applies with--keep-bothtoo, so a repeated run does not make a third copy.--replacealways uploads.
Bug Fixes / Hardening
- A 503 from a busy storage pool on a chunk is retried after a pause instead of failing the file. This holds at every setting, including
--parallel 1. - The resume record is written whole: a kill mid-write can no longer leave half a record. A push interrupted while its last step was running finishes the file on the next run, without sending a chunk.
- A resumed upload finishes in the folder you asked for. Before, a push that was interrupted and run again with a different
--foldercould complete the file in the folder the first run had used, and print nothing about it. Now an interrupted upload continues only when it sits in the folder this push writes into. Otherwise the old upload is ended on the server, which removes its never-completed entry, and the file starts again in the right folder. The file is never moved. - No guessing when the CLI cannot tell who can see a folder. If the server does not say, or the sharing lists do not load, the folder counts as shared: you are asked, or the push refuses without a terminal, unless you passed
--reuse-shared. When several folders have the same name and the CLI cannot tell which one is private, nothing is uploaded, also with--reuse-shared. - No duplicate when a name check cannot be read. If the folder listing for the name check fails, or a same-name entry might be a file-request upload whose keys did not load, that file fails with a reason instead of being uploaded a second time. An entry this device can never open is passed over, so it does not block every push into that folder.
- The log of finished uploads is owner-only.
finished-uploads.jsonl, which names the local paths of files you pushed, is written with mode 0600, and an existing log is brought to 0600 too. - A file that changes size after the push planned it is counted at its new size, and a file that fails stops counting toward the time left.
- The rate-limit pause message is printed above the live lines instead of tearing them.
bb backuprefuses to mix stores up. Its state file is tied to your account and to this machine. A file from another account, or from another machine, is refused with the name of the file to delete, instead of being reset in place. A device folder that was deleted is dropped when you add a folder again, rather than reused.- A destination
bb pushcannot place stops the push with "could not check whether the destination folder is inside Backups" and the reason, instead of guessing that it is outside.
Compatibility
bb pushnow sends 4 chunks at once by default.--parallel 1sends the same requests as 0.15.0, except that a 503 on a chunk is now retried. Files between 1 and 2 GiB use 32 MiB chunks at--parallel 7and8. An upload interrupted by an olderbbresumes one chunk at a time, in its own chunk size.bb syncandbb backupare unchanged.- Behaviour you may notice:
- A same-name shared folder now stops a script. Pushing a folder where a folder of that name already exists and is shared (or the CLI cannot tell who can see it) asks at a terminal. With no terminal,
--jsonor--quietit uploads nothing and exits with code 2. In 0.15.0 the same push made a new private folder and exited 0. A script that wants the shared folder passes--reuse-shared; one that wants a private folder pushes under a different name. - An unchanged re-push now exits 0. Running a completed, unchanged
bb pushagain used to refuse with "already exists" and exit 2 without a terminal. It now skips the file, printsskipped N already uploaded(total_already_uploadedin--json) and exits 0. A changed file, or one this machine did not upload, is still a conflict and still exits 2.--replacealways uploads.
- A same-name shared folder now stops a script. Pushing a folder where a folder of that name already exists and is shared (or the CLI cannot tell who can see it) asks at a terminal. With no terminal,
bb rm -f/--forcenow only skip the move-to-trash prompt.--yesanswers every question. A script that used-fto answer "Delete 's backup?" must pass--yes; with no terminal and no--yes, that question exits 2.- Not covered yet:
bb sync,bb mount,bb webdav,bb repairandbb restoredon't check the Backups rule. A later release adds it; until then, don't use them to change files inside Backups. - Interrupted uploads recorded by an older
bb: the old record does not name its folder. If the server can tell where the upload sits, that decides. If it cannot, that file fails once for that run and its record is kept. - Sharing lists: the folder check reads who a folder is shared with and its links from the same sharing endpoints the web app uses. A server that does not offer them is treated as "cannot tell", never as "private".
- An older CLI with this server: unchanged.
- Dependency changes:
libc0.2.186 → 0.2.191,serde_json1.0.149 → 1.0.154,regex1.12.3 → 1.13.1 (withregex-automataandregex-syntax).unicode-width0.2 is now a direct dependency, used to fit names by display width; it was already in the build.- Uses Beebeeb core v0.2.1 (
a5413d2);bb backupalso uses core'sbeebeeb-backupcrate at the same revision.
Verification
- Test suite on Linux in CI, default features, at the last code change of this release: 1,216 passed, 0 failed, 5 ignored (45 test result lines). This release differs from that commit only in the version line, the release notes and the changelog. The tests run the real
bbbinary against a local mock of the server, with a pseudo-terminal where a prompt is involved; none of them talks to production. - Lint: the CI jobs for Clippy with warnings denied and rustfmt, for Clippy with the
fusefeature, and for the installer update regression passed at that commit. - Review: the folder-push changes went through several rounds of code review before they were merged. A security-focused review of the first version found three blocking problems (
--folderreusing a shared folder when a private one existed, a file-request list that did not load, and an unknown sharing state treated as a guess); all three are fixed in this release, and each fix has a test that fails without it. A review ofbb backupfound problems in its safety paths (a state file from another machine, a deleted device folder, a manifest that could not be written,rm -fanswering the device question); these are fixed in this release too, each pinned by a test that fails when the fix is undone. - Not run for this release: the test suite with
--features fuse. Release binaries ship without FUSE, so the mount is not part of what you install.
Install / Update
bb update
bb --version # bb 0.16.0Homebrew: brew upgrade beebeeb-io/tap/bb. Scoop: scoop update bb. New installs: curl -fsSL https://get.beebeeb.io | sh. Restart a running bb sync daemon after updating.
Full changelog: v0.15.0...v0.16.0