Radicle is a peer-to-peer, local-first code collaboration stack built on Git.
Radicle 1.10.0 – Sunflower
05.08.2026The Radicle team would like to announce the release of Radicle 1.10.0, code name Sunflower. Did you know that only young sunflowers track the sun? When have you last admired the beautiful floret arrangement of a sunflower?
This release contains 143 commits by 16 contributors, and we would especially like to thank:
- Arthur Mariano
- Daniel Norman
- Daniel Silverstone
- Fabrice Bellamy
- Fred Gobry
- Richard Levitte
- Robin Heggelund Hansen
- Rūdolfs Ošiņš
- Wiktor Kwapisiewicz
- nullcurve
- stefan
- zebus
Installation
curl -sSf https://radicle.dev/install | sh -s -- --no-modify-path --version=1.10.0
Towards Radicle 2.0.0
Work on the next major version of Radicle has started.
Join the discussion about it on Zulip.
Following the release of Radicle 1.10.0, refs/heads/master will be used for development of Radicle 2,
while backbports will target refs/heads/releases/1 for maintenance of Radicle 1.
In this Release
Repository Identity Evaluation
The limitations of evaluating repository identities were found on multiple
repositories, including the heartwood repository. This prompted a review of
the evaluation logic, which resulted in several improvements.
The bulk of the improvements come from two aspects in the evaluation. The first is keeping track of the parent and children relationship of revisions. The second is having a richer model of a revision’s state.
Every revision (except the initial revision which is created during rad init)
explicitly refers to a parent revision. This is similar to Git commits, which
usually refer to one parent. Similarly, root commits do not refer to any parent,
and merge commits refer to multiple parents. For repository identity, merges
are not possible. This gives the first relation of interest: We say that two
revisions A and B are in relation “parent” if A refers to B explicitly
as its parent. The inverse relation is called “child”. The transitive closure
of “parent” is called “ancestor” and the transitive closure of “child” is called
“descendant”. Further, we say that two revisions A and B are in relation
“sibling” if they are both in relation “parent” with the same revision C.
With these relationships in mind, a revision can now be in one of four states:
- Active: this is the initial state of any revision when it is proposed. The proposal is waiting for delegates to accept or reject it. Or alternatively, the revision can be redacted. A revision will remain active, even if it has a majority of accepted votes, if its parent is still active.
- Accepted: the revision was accepted by a majority of delegates. The revision can no longer be rejected nor redacted. When a revision is accepted, its children are also evaluated, recursively, to see if they also have reached a majority.
- Rejected: there are now three variants of rejection for a revision: a. The revision was directly rejected by a majority of the delegates, by them casting their rejection votes. b. The parent of the revision was rejected, and thus this revision was transitively rejected. c. A sibling of the revision was accepted, and thus this revision (and all other siblings) are rejected.
- Redacted: there are two variants of redaction for a revision: a. The author explicitly redacted (withdrew) the revision. b. The parent of the revision was redacted, and thus this revision was transitively redacted.
This modeling of revisions ensures that the evaluation of the state remains consistent, and accounts for the previous cases we had come across in the wild.
The final ingredient that was added ensures that the evaluation remains
consistent when it involves delegates accepting a revision. A delegate can only
accept a revision if they have not accepted any other active revision that is a
sibling of the revision they are voting on.
This prevents scenarios such as Alice creating and accepting two revisions A
and B, and Bob and Eve accepting each respectively. Both revisions would then
reach majority, but the evaluation would pick one arbitrarily based on the
topological sort of the COB graph. However, with the above condition in place,
this cannot happen.
We will note that we found an inconsistency where the concurrent operations “redact” and “accept” will produce a different identity document depending on which is ordered first. Further analysis of the ordering of pairs of actions is required, but is left to future work.
We scanned the network for cases where these changes in evaluation also lead to changes in the identity document. There are some cases, but this happens rarely: Out of several thousand repositories, only around fifteen showed differences.
In case your repository is affected, you might need to run rad id cache. This
re-evaluates the identity COB and updates the refs/rad/id reference.
Improvements
rad patch listincludes aLabelscolumn, showing any assigned labels to the patch.- The node can now be configured with a per-stream timeout. A new configuration
key under
node.limits.fetchTimeoutis added and the default value remains 30 seconds. This default is suitable for TCP connections. However on the Tor and I2P transports, which are higher latency, a larger timeout avoids spurious aborts during tunnel rebuilds or congestion.
Fixed Bugs
- Previously, a delegate could push to the default branch, for the first time, while attempting to merge a patch. However, the patch would not be marked as merged. The Git remote helper will now fallback to the canonical default branch, if the default branch of the delegate could not be found, and correctly mark the patch as merged.
rad patch reviewpresents an appropriate error to the user when the user does not provide an option, one of--acceptor--reject, or a summary message.
Changelog
4641c342cRelease 1.10.0 lorenz.leutgeb@radicle.dev1a5dfc261surf: Fix flakey test with sorted vector adrian.duke@gmail.com4f7bde023surf: Ignore Rust and JSON examples fintan.halpenny@gmail.coma2eb75688cli/id: Introducerad id cachelorenz.leutgeb@radicle.devca1b4fa7bcli/id: Add verbose output to show and list adrian.duke@gmail.comc830053e3cli/id: Incorporate reason for rejection adrian.duke@gmail.com71a91042dcargo/workspace: Bump crate versions lorenz.leutgeb@radicle.devac607c8cagit-ref-format: Integrate with workspace lorenz.leutgeb@radicle.dev8731d01bcgit-ref-format: Copy over from radicle-git lorenz.leutgeb@radicle.dev36fc031dasurf: Switch to crate in workspace lorenz.leutgeb@radicle.xyzf8b5bde40surf: Refactor lorenz.leutgeb@radicle.xyze880810e4surf: Move test files into place lorenz.leutgeb@radicle.dev0ef1f0714surf: Copy over from radicle-git lorenz.leutgeb@radicle.xyz64a028353scripts/just/check-ellipses: Replace less lorenz.leutgeb@radicle.deve9b999e2dprotocol: Calmtyposlorenz.leutgeb@radicle.dev474b7f369cargo/workspace: Add “no-std” category lorenz.leutgeb@radicle.deva71f3b729cargo/workspace: Remove workspace version lorenz.leutgeb@radicle.deve373f80d0cargo/workspace: Add repository metadata lorenz.leutgeb@radicle.deva0551416fcargo/workspace: Remove homepage lorenz.leutgeb@radicle.dev69a4da6ffcargo/workspace: Reorder package metadata lorenz.leutgeb@radicle.dev024006297cargo/workspace: Removepackage.authorsmetadata lorenz.leutgeb@radicle.devcaf45f152cli: Tighten visibility and minimizepub uselorenz.leutgeb@radicle.devc2af4b598signals: Fix Windows lorenz.leutgeb@radicle.dev2ae6301f8cargo/workspace: Bump crate versions lorenz.leutgeb@radicle.dev008b1a25eflake/nixpkgs: 25.11 → 26.05 lorenz.leutgeb@radicle.devee8b7919fcrypto: Add conditions forPublicKey::to_byteslorenz.leutgeb@radicle.dev0a2981d78term: Fix features for zeroize lorenz.leutgeb@radicle.deva87e0bd1cbuild/Dockerfile: Install Zig viaapklorenz.leutgeb@radicle.dev8d50b7582build/Dockerfile/zig: 0.13.0 → 0.16.0 lorenz.leutgeb@radicle.dev4751432b3build/Dockerfile: Specify Registry docker.io lorenz.leutgeb@radicle.dev828bfd02fbuild/Dockerfile: Re-use$ALPINE_VERSIONlorenz.leutgeb@radicle.dev394ade557build/Dockerfile/alpine: 3.24 → 3.24 lorenz.leutgeb@radicle.dev0f8e1cc59build/Dockerfile: Omit defaultRUST_VERSIONlorenz.leutgeb@radicle.deve0dc14de2protocol/handle:ResponderinCommand::Blocklorenz.leutgeb@radicle.dev3658ece34node/test: Clean up lorenz.leutgeb@radicle.dev8efbf06f7node: Clean upuses lorenz.leutgeb@radicle.dev9eeecacf2node: Remove re-export…::node::PROTOCOL_VERSIONlorenz.leutgeb@radicle.devf45a96f0ecargo/dev: Optimize compute-heavy dependencies lorenz@leutgeb.xyzdf6524e7ecrypto: Rewrite lorenz.leutgeb@radicle.dev0fd0104e8radicle, cli/auth: Let binary crate generate seed lorenz.leutgeb@radicle.dev8ceef3c40crypto/test: Diffie-Hellman Fixture lorenz@leutgeb.xyz66ab7f35ctreewide: Add configurable per-stream fetch timeout dev@example.com027de89cdnode/worker/garbage: Clean up lorenz.leutgeb@radicle.dev188f3041dflake.nix: Remove darwin.apple_sdk.frameworks as it is deprecated git@heghan.org41d776be4treewide: Use channels fromstd, not Crossbeam lorenz.leutgeb@radicle.devf31fbf40crust: 1.95 → 1.97.1 lorenz.leutgeb@radicle.dev6d846d754radicle: MarkAddressTypeasnon_exhaustivelorenz.leutgeb@radicle.devcff80006aprotocol: Remove duplicateenum AddressTypelorenz.leutgeb@radicle.deve4775edf4radicle: Remove dependencyamplifylorenz.leutgeb@radicle.dev564c167degit2: 0.20 → 0.21 lorenz.leutgeb@radicle.devf897cbbf2protocol: Remove unused radicle-crypto dev-dependency fintan.halpenny@gmail.comfa14b68e2cli-test: Remove unused radicle dependency fintan.halpenny@gmail.comef7d8bb75node: Remove unused qcheck-macros dependency fintan.halpenny@gmail.com8ad86c68cterm: Remove unused tempfile dependency fintan.halpenny@gmail.com6e06c0515schemars: Remove unused serde dependency fintan.halpenny@gmail.com07b838adblog: Remove unused dependencies fintan.halpenny@gmail.com2590fc50cfetch: Remove gix-refpsec dependency fintan.halpenny@gmail.combdbe1e407cli: Remove unused dependencies fintan.halpenny@gmail.com837ee79d2flake.nix: Add cargo-shear fintan.halpenny@gmail.com27e2a9428node: Refactor Tests lorenz.leutgeb@radicle.deva079825afnode/reactor: Simplify Transport lorenz.leutgeb@radicle.dev4e22e929dnode/reactor/session:Protocol::{state → machine}lorenz.leutgeb@radicle.dev7d5248a89node/reactor: Remove unnecessary functions/types lorenz.leutgeb@radicle.devb5e6d8276radicle/identity: Tidy up lorenz.leutgeb@radicle.devcd57affc3cargo: Bump zlib-rs to 0.6.5 rudolfs@osins.orgfb80d58afCHANGELOG: Describe the changes to repository identity evaluation fintan.halpenny@gmail.com2f1aaa45bradicle/cob/identity: Add sibling-accept invariant to property tests fintan.halpenny@gmail.coma63f91885radicle/cob/identity: GuardIdentityMut::updateagainst sibling proposals fintan.halpenny@gmail.comb6f07074dradicle/cob/identity: GuardIdentityMut::acceptagainst sibling accepts fintan.halpenny@gmail.com7daeb3135radicle/cob/identity: Add SiblingAccepted error variant fintan.halpenny@gmail.com654218e6aradicle/cob/identity: Strip implicit author accept for sibling revisions inactionfintan.halpenny@gmail.com82dc3fe20radicle/cob/identity: Enforce sibling-accept invariant forRevisionAcceptinactionfintan.halpenny@gmail.com8e677a9d9radicle/cob/identity: Add has_active_sibling_accept helper fintan.halpenny@gmail.com62f64744aradicle/cob/identity: Test accept-before-redact convergence fintan.halpenny@gmail.comf720526fcradicle/cob/identity: Test concurrent redact-vs-accept convergence fintan.halpenny@gmail.com21700e496radicle/cob/identity: Fix cascading_rejections test to test actual cascading fintan.halpenny@gmail.comebf0f417fradicle/cob/identity: DeprecateIdentity::idlorenz.leutgeb@radicle.dev97f279fe4radicle/cob/identity: Test redacting accepted revisions fintan.halpenny@gmail.come0e231813radicle/cob/identity: Testauthorization_based_on_parent_not_currentfintan.halpenny@gmail.com108686e29radicle/cob/identity: Test queued children with delegate change fintan.halpenny@gmail.comda2c523d4radicle/cob/identity: Add Property Tests adrian.duke@gmail.comaae8938c0radicle/test/arbitrary: Make BoundedVec shared fintan.halpenny@gmail.com94a24a728radicle/cob/identity: Fix comments in testreject_concurrentadrian.duke@gmail.com2768fe79dradicle/cob/identity: Test evaluating children of accepted revision adrian.duke@gmail.comc174efccbradicle/cob/identity: Test cascading of redaction adrian.duke@gmail.com2349eebf5radicle/cob/identity: Test cascading rejection adrian.duke@gmail.com39972b0c4radicle/cob/identity: Test terminal states adrian.duke@gmail.com489360d0eradicle/cob/identity: Add concurrent terminal state test adrian.duke@gmail.comba4a79af9radicle/cob/identity: Test rejected sibling lorenz.leutgeb@radicle.xyzd8c14222aradicle/cob/identity: Rewrite Evaluation lorenz.leutgeb@radicle.xyzb145b95eeradicle/cob/identity: Use verdicts to count votes lorenz.leutgeb@radicle.xyz442df34beradicle/cob/identity: Strengthen test assumptions lorenz.leutgeb@radicle.xyzee1710950Fix NO_COLOR to only suppress colors, not all ANSI styles richard@levitte.orgb12c0f0beradicle-cli: fix tests for git ddiff on Windows. fred@epthos.netd973a548bnode/wire: Test connected node removes active fetch daniel@norman.life3459ad57cnode/wire: Test disconnected node remove active fetch daniel@norman.life665e640fenode/test: Reproduce orphaned fetch at service layer daniel@norman.lifed230ff72efetcher: Test removing active fetch from another node daniel@norman.lifedf1e3e612fetcher/state: Extend test for same RID, different nodes fintan.halpenny@gmail.com4a05e52bafetcher: Guard fetched against stale node results daniel@norman.life7b910476cnode/wire: Always report fetch results to the service daniel@norman.life1070b777dradicle-cli: Remove fullstop from RID on rad init adrian.duke@gmail.com018266023cli/examples: fix jj-init-colocate test stefan.r.boca@gmail.com07f748475radicle/cob: Include command name on spawn fail dsilvers@digital-scurf.org88bf2a964term: Remove typing indication for passwords lorenz.leutgeb@radicle.deve991bd747cli/examples: Introduce a suite of merge and revert tests for patch.target adrian.duke@gmail.com178bda36dradicle-cli/terminal: Add patch target ref to rad patch show adrian.duke@gmail.comeb2dded0eremote-helper: Introduce magic push ref ‘refs/for/’ adrian.duke@gmail.com06e201c92remote-helper: Add ‘patch.target’ push option adrian.duke@gmail.comf0c6abc6eradicle/cob/patch: Extend MergeTarget adrian.duke@gmail.comc7339615acob: Replace ‘git2::Oid’ -> ‘git::raw::Oid’ adrian.duke@gmail.comdb4ad27b4radicle-cli: Fix broken test ‘rad-cob-update’ adrian.duke@gmail.comd734d6926radicle-cli: Add labels column to patch list adrian.duke@gmail.comfda165ffcradicle: Replace WAN routeable testing IPs with 198.18.0.0/15 private subnet adrian.duke@gmail.com55b4b0400radicle-node: Replace WAN routeable testing IPs with 198.18.0.0/15 private subnet adrian.duke@gmail.coma294e0573radicle-node: Prevent infinite connection loop on instant dial failure adrian.duke@gmail.come4a16dc40cli-test: Disable normalizing paths fintan.halpenny@gmail.comb397b1a24workspace: Update snapbox to 1.2 fintan.halpenny@gmail.com09e6147efradicle/node/config: Document RateLimit fields fintan.halpenny@gmail.com90aaec1c9CONTRIBUTING: Add section on issue labels fintan.halpenny@gmail.coma3ff596e2scripts/changelog: Generate links to commits on seed.radicle.dev fintan.halpenny@gmail.coma65ac048ccob/change_graph: Log Errors lorenz.leutgeb@radicle.xyz9ff0e8b01just: checking for ellipses fintan.halpenny@gmail.com9c3751161Revert “typos: Rule for … -> …” fintan.halpenny@gmail.com81fd14113Revert “codespell: Rule for … -> …” fintan.halpenny@gmail.comf49cc5defradicle-node.1.adoc: Fix markup error <did:key:z6MkpP5WGopov3BTRK9dmCo5TmqngpAuJ57JW8cywPggZ8HP@radicle.xyz>dd7c13271rad-patch.1.doc: Fix typos and markup errors <did:key:z6MkpP5WGopov3BTRK9dmCo5TmqngpAuJ57JW8cywPggZ8HP@radicle.xyz>898e00ecfCONTRIBUTING: Fix typo <did:key:z6MkpP5WGopov3BTRK9dmCo5TmqngpAuJ57JW8cywPggZ8HP@radicle.xyz>0bbedb965cli: Fix panic onrad patch reviewwithout options arthvm@proton.me804fa3e44cli/examples: rad-patch-merge-on-first-push fabrice.bellamy@distrilab.frcf2829447remote-helper: Account for first push from delegate fabrice.bellamy@distrilab.frc70d4a29eCHANGELOG: Backfill 1.9.1 updates fintan.halpenny@gmail.comcf108311dnode: Heap Profiling with DHAT lorenz.leutgeb@radicle.devd8bf84c17CONTRIBUTING: modify notes on preparing commits fintan.halpenny@gmail.com3e1a02fdbCONTRIBUTING: includesuperin import examples fintan.halpenny@gmail.com01df41bf0CONTRIBUTING: document the use of the terms safe and unsafe fintan.halpenny@gmail.com70c2f89bdCONTRIBUTING: reword section on unwrap and expect fintan.halpenny@gmail.com21608788cCONTRIBUTING: mention nextest fintan.halpenny@gmail.com87347bdfaCONTRIBUTING: clean up lint and formatting section fintan.halpenny@gmail.com05507f21aCONTRIBUTING: mention--log-levelfor logs fintan.halpenny@gmail.com0a03f1c84crypto: Handle defaultSSH_AUTH_SOCKon Windows fred@epthos.net067a9d13bjustfile: Add--checktocargo fmtfintan.halpenny@gmail.com998ff91e2cli/id: Print Parent of Revision lorenz.leutgeb@radicle.xyz
Checksums
5551ca8356bc1dd7e80ba2a31ac907e1bc1cca7af079e4f99b13e71a4e91d05c radicle-1.10.0-aarch64-apple-darwin.tar.xz
2db9fdd49d85fd0a067cd07cddcba61d7136730caa926df68555f653921d3ebc radicle-1.10.0-aarch64-unknown-linux-musl.tar.xz
55099ff08d835bd091c0857434c0671c1ebb5df8eca4c29704ba8c5ba95de768 radicle-1.10.0-x86_64-unknown-linux-musl.tar.xz
de0042fd3230b294cf0cd2478008e14773a3a5a10c168f9bf5bb1d2de8ca1bb9 radicle-1.10.0-x86_64-apple-darwin.tar.xz