Repository navigation
v2.0.0
rbox 2.0 is the release where sync gets fast and honest. Everything rbox
remembers about your folders now lives in a single SQLite database instead of a
large JSON file it rewrote from scratch every few seconds — which is what made
the old version slow. A typical "nothing changed" sync went from 7.4 to 1.5
seconds on the Linux workstation and from 6.6 to 2.7 seconds on the MacBook;
the busiest machine in the fleet, with more than a hundred Git repositories,
went from 44 seconds to 8.2 seconds to pick up a change. The rest of 2.0 is
about being understandable while it works: the Git side of sync now explains
what it is waiting on in plain English, offers a real way to resolve it, and
the file watcher recovers on its own instead of quietly giving up.
Breaking changes
- Upgrading from 1.x works, and rbox repairs itself along the way. Run the
installer (orrbox upgrade), restart rbox, and it converts each folder's
bookkeeping on its own. It checks every folder BEFORE stopping anything, so
an upgrade never takes sync down; a folder it genuinely cannot work out is
left alone with sync still running elsewhere, and rbox prints
rbox config regenerate— the command that actually fixes it. Your files
are never part of this conversion: only rbox's own records change format.
(#688, PR #774, design 276.)- There is no
rbox migratecommand and no conversion job to babysit —
the upgrade does it in place. Starting fresh also works, if you prefer:
install 2.0, run setup, point it at the same folder. - The sync manifest schema is still 4, as it was in 1.11.4. A handful of
internal wire fields were renamed for clarity, and 2.0 accepts both the
old and new names during the transition, so your machines can upgrade in
any order. (PRs #804/#806.) What changed most is how each machine stores
its own local record of what it has seen.
- There is no
- A 1.x machine that does get the new binary keeps syncing. Earlier 2.0
betas could leave background sync switched off after an upgrade, because a
1.x machine has synced folders but no folder-configuration file and the new
binary refused to start without one. rbox now writes that file from the
folders it can already see, decides each folder on its own, and leaves sync
running if something genuinely cannot be worked out — printing
rbox config regenerate, the command that actually fixes it. (#688, PR #774,
design 276.) ~/.rbox/config.jsonis now the authority for which local folders rbox may
sync, and for their safe sync options. Existing local bindings are
preserved, but a machine that has bindings and no catalog must explicitly run
rbox config regenerate— rbox will not guess after a missing or damaged
catalog. Inspect withrbox config, admit a detached folder with
rbox config add <path>, and fix a proven local folder move with
rbox config repair <path>. (Design 231.)- The
nextpreview channel does not roll forward on its own. If you
installed a 2.0 beta fromrbox.to/next/install.sh, that choice persists
beside the installed binary; runrbox upgrade --channel latest(or the
stable installer) once 2.0.0 is out, or you will sit on the last beta. - The
v2.0.0-beta.1throughv2.0.0-beta.4prereleases went only to the
founder fleet'snextchannel. Their changes are folded into this section;
there is nothing separate to read.
Added
-
Per-folder ignore paths in
~/.rbox/config.json(options.ignorePaths
on a folder entry) — machine-local excludes that never drive deletes on
your other computers, applied live without a restart. Useful for keeping a
giant build tree (say, a browser checkout) out of sync on one machine. -
Setup speaks "folders". The guided flow offers three plain choices — sync
~/rbox, sync another folder on this computer, or sync a folder from another
machine — instead of asking about workspaces. (Design 230.) -
rbox statuscounts the conflict copies rbox saved for you and that are
still sitting in the folder, so they are visible without hunting for
*.conflict*files by hand. Also inrbox status --jsonas
conflictCopies. A moved-aside folder counts as one thing to deal with,
however many files it holds. -
Paused Git repos now explain themselves in plain English and can be
resolved in bulk.rbox git resolvegained a per-repo view, a--dry-run
that tells you honestly what it would and would not copy, and a batched
--under <folder> keep-minethat shows you the count and requires you to
confirm it (--yes --expect-repos <n>for scripts). Each paused repo is
grouped under a short story — "you have uncommitted work here" and twelve
others — rather than an internal reason code. (Design 273, #764.) -
A "conflict copies" reason for paused folders. When the only thing left
to compare in a folder is copies rbox saved during an earlier conflict, sync
says so — "only conflict-copies remain here, so the comparison was skipped" —
instead of pausing without explanation. -
RboxBar ships with every release, and
rbox upgrademanages it. The
macOS menu bar app is published alongside the CLI binaries for each tag, and
on macOSrbox upgradeinstalls, updates, and restarts it automatically
(opt out withRBOX_NO_MENUBAR_APP=1). Installing through the CLI avoids
macOS's unsigned-app first-launch friction entirely; only a zip downloaded
in a browser still needs right-click → Open. (PR #801, design 282.) -
Every release tag now also creates a GitHub Releases entry with that
version's changelog section. (#649.)
Changed
- rbox's local record of your folder now lives in SQLite instead of a JSON
file. New folders are created that way from the first sync; the old
JSON-writing code, its conversion job, and the commands that supervised it
are gone. (Designs 262/266, ~19,000 lines deleted.) - A machine that only receives (pull-only) now uses the live file watcher
too, so it reacts to changes instead of waiting for the next scan. Pull-only
now means exactly one thing — this machine does not publish. (Design 277,
#477.) - macOS folder scans use the native bulk directory walk by default; no
environment opt-in. Capability, directory-probe, and per-directory fallback
guards remain. On Linux the equivalent walk is about 5× faster than before. - A degraded file watcher is now named outright by
rbox status, rather than
showing up only as unexplained slowness. rbox doctor'smigrationcheck is now calledgenesis, matching what it
actually checks.
Fixed
-
rbox git resolveearned its stripes the hard way. A resolve week on
the development fleet fixed six distinct refusals: repos whose sync
evidence predated their records now heal or explain themselves precisely
(naming the branch and the mismatch instead of "may have partially
applied"), a stale git commit-graph cache can no longer fail the
completeness check, the safety boundary now recognizes its own bookkeeping,
and a repo needing many housekeeping passes no longer gives up at eight —
or spins forever. When a repo's copy is missing history only another
computer can supply, status now says exactly that and names the one
command that fixes it. -
Background sync no longer rings its own doorbell. A no-op push loop on
Linux (roughly one cycle every 3 seconds, forever) came from the Git watcher
reacting to rbox's own bookkeeping writes. -
The publish/conflict storm is gone. One machine publishing empty
sequences forever could make another machine lose every race and burn six
full Git plans per attempt, pinning a CPU core for the better part of an
hour. Permanent "pending" work is now distinguished from a transient unclear
state, and the internal retry loop surrenders after a bounded window. (#683,
#685, design 244.) -
The file watcher recovers on its own. A burst of operating-system watch
events used to blow a one-way fuse and leave the daemon scanning forever;
overflow now counts 5-second episodes anchored at the first drop, and the
watcher re-arms under a supervised witness check. (Designs 237, 277.) -
A Git repo whose local copy rbox cannot verify no longer re-downloads the
same history every few seconds. Repos in that state were downloading,
unpacking, and re-checking unchanged history forever, slowing every other
repo behind them. rbox now re-checks such a repo once an hour — and still
immediately when you commit in it or another machine sends something new.
(Design 278;RBOX_GIT_CONNECTIVITY_SKIP=0restores the old behaviour.) -
Conflict copies no longer make a folder look permanently out of sync, and
deleting the last conflict copy clears the hold on the same sync cycle
instead of telling you to delete files rbox had just removed. An ignore rule
that happens to match conflict-copy names (e.g.*.conflict*) no longer
pauses every folder it applies to. (Design 272, #659.) -
Leftover files from finished Git operations no longer strand other
machines. ConcludedAUTO_MERGE,MERGE_MSG,REBASE_HEAD, and draft
merge messages are recognised as finished and cleaned up by the next
completed sync checkout; genuinely in-progress merges still wait, and
linked-worktree problems now name the responsible worktree. (Design 236,
#667 — enabled for everyone in 2.0.) -
The message for a paused Git repo is true. It no longer says rbox
"couldn't finish downloading the other computer's version" when the download
succeeded — it says rbox couldn't put that version in place here. -
A paused merge on another machine used to cost about 9 seconds of every sync
cycle on this one; rbox now remembers the stuck state instead of
re-discovering it from scratch. -
Mismatch pauses now name the specific paths that differ, instead of reporting
that something, somewhere, disagreed. -
rbox statusno longer intermittently reports "sync halted" on a perfectly
healthy machine — a read-only health check was racing the live writer.
(#765, design 276.) -
Files rbox had already been told to ignore no longer linger in the synced
set, and a barenode_modulesignore rule now matches at any depth, the same
way.gitalways did.
Performance
- Sending a change is 4-5× faster. A "nothing changed" push went from 7.4s
to a 1.5s median on the Linux workstation and 6.6s to 2.7s on the MacBook.
(#661, design 277.)- The push cycle was materializing rbox's entire state five times per cycle;
it now does so at most once (RBOX_STATE_LOAD_CACHE=0restores the old
behaviour). - A separate 51-second tail on content pushes was settlement waiting for the
next scan tick; settlement now happens at each operation boundary
(58.5s → 7.0s wall on the workstation).
- The push cycle was materializing rbox's entire state five times per cycle;
- Receiving a change is dramatically faster on machines with many Git
repositories. The 100+-repo host went from 44s to 8.2s per pull.- Zero-change saves compose a minimal packet instead of rewriting the whole
state (zero-change pull 13.3s → 3.6s;RBOX_SAVE_NOOP_ELIDE). - Content-carrying saves write and verify only the entries that changed
(one-changed save ~2.8s → ~60ms; MacBook 1-blob receive 20.4s → 9.0s;
RBOX_SAVE_DELTA). - The internal Git lock ceremony was rewritten from an O(N²) journal to an
append-structured one with batched directory fsyncs (acquire 50.3s → 16.4s
at 2,292 locks), and then scoped to only the markers a given pull actually
authors — the busy host now takes zero locks on a steady pull, down from
1,882 (RBOX_CAS_DELTA_LOCKS=0). (Designs 268, 279.) - Repos that are paused and unchanged skip their per-repo work entirely
(~3.5s → ~53ms per repo per cycle), including ones held by a base-composer
artifact (RBOX_GIT_HELD_SKIP_COMPOSER). - Applying incoming Git work on the workstation went from 45.3s to 1.3s once
checkout blockers were properly typed, and a repeatedly re-probed wedged
repo went from ~2.5s to ~10ms per push.
- Zero-change saves compose a minimal packet instead of rewriting the whole
- Sync status lines now attribute lock counts (
locks<N> blocked<M>) so
durability work is distinguishable from real contention, and per-hop
propagation timings can be traced end-to-end with exact sequence correlation.
Known limitations
Things we know about, judged safe to ship, and are telling you straight —
each has an open issue:
- A Git repo whose sync journal rbox cannot read re-checks itself on a slow
cycle and stays paused rather than guessing;rbox statusnames it.
Resolution work is queued. (#775) - If you stop rbox while it is mid-write on a very busy machine, the stop can
time out and force-quit after 60 seconds, occasionally leaving a stale lock
file that pauses one repo until the next sync cycle clears it. (#672) - A Git repo whose checkout is behind its synced branch can briefly show new
file contents before Git itself catches up; rbox pauses the Git side rather
than guess, and tells you. (#669) - Commands that restore old versions (
rbox versions,rbox trash restore)
currently read paths relative to the synced folder's root, not your current
directory — run them from the folder root to be safe. (#516) rbox ignorewith a bare flag and no pattern currently does nothing useful
and does not say so. Give it the pattern explicitly. (#518)- A Git repo with an enormous configuration (over 512 keys) cannot sync its
config changes; everything else in that repo still syncs. (#702) - Extra local files that were never part of sync (including rbox's own saved
*.conflict*copies) can keep one repo's background self-check
permanently unsatisfied. It is a diagnostic annoyance, not a sync fault.
(#659)
The
v2.0.0-beta.1–v2.0.0-beta.4prereleases shipped only to the
founder fleet'snextchannel; their changes are folded into 2.0.0 above.
v2.0.0-beta.3was tagged but never published.v2.0.0-beta.5was the
release-pipeline dress rehearsal.