| + |
---
|
| + |
title: "End of Year Roadmap – 2025"
|
| + |
image: radicle-1.png
|
| + |
layout: blog
|
| + |
---
|
| + |
|
| + |
## The Road Ahead
|
| + |
|
| + |
After the initial 1.0 release, the team was busy polishing certain aspects of the Radicle tooling and stack.
|
| + |
This work resulted in 1.1, 1.2, 1.3, and most recently 1.4.
|
| + |
We can really feel the momentum, and we could not have done it without the help from contributors also weighing in on the discussion and submitting patches.
|
| + |
|
| + |
We are close approaching the anniversary of that first release, and as the project matures, we wanted to take this opportunity to share a roadmap with you.
|
| + |
The aim is to provide some transparency towards what we want to work on, and to also help contributors focus their attention on ongoing topics.
|
| + |
|
| + |
This is not necessarily a commitment to getting this work done within a certain time frame.
|
| + |
We will always try to aim to work on features and fixes that will provide the best experience for you and ourselves.
|
| + |
|
| + |
Without further ado, let's put on our cartographer hats on and map out the direction of the Radicle protocol over the coming months!
|
| + |
|
| + |
## Project Management
|
| + |
|
| + |
First things first, we'll discuss some general management of the project itself.
|
| + |
We want to touch on our release management process and how we will practice cutting new releases and maintaining patch versions going forward.
|
| + |
|
| + |
### Release Management
|
| + |
|
| + |
The Radicle Protocol team are aiming to improve their release process going forward.
|
| + |
The previous process has got us this far, but we feel like it's time to take the next step towards more mature workflows.
|
| + |
|
| + |
First, we will quickly discuss the current release process.
|
| + |
As a maintainer, @fintohaps has been using the scripts that are available in `heartwood`: `build/tag`, `build/build`, `build/upload`, and `build/release`.
|
| + |
In order, these scripts achieve tagging a commit for release, building the binaries – via `cargo-zigbuild` for cross-compilation, uploading the binaries to our file server, and finally, marking a binary as the latest.
|
| + |
This uses @fintohaps' key material for signing and verification, and unfortunately, ties the whole process to them.
|
| + |
Before the advent of canonical references, it also meant that it was tied their particular namespace.
|
| + |
The final note here is that we would only release under minor versions and never attempt to create patch or hotfix releases.
|
| + |
|
| + |
Proceeding forward, we want to tackle each of these problems to grow towards a healthier release process.
|
| + |
The goal is to have a rotating release maintainer.
|
| + |
For this to happen, the team will share a release signing key.
|
| + |
This will be used to sign the tags for the releases, and can be used by others to verify our releases.
|
| + |
For historical releases, we will ensure to list the older keys that were used to build them – which will also pave the way for rotating the release signing key.
|
| + |
|
| + |
We will also begin to release patch and hotfix versions.
|
| + |
The process will be based on a contributors suggestion, and blog post ([How to Do Releases]) – thanks Matthias.
|
| + |
When a Radicle patch provides a fix or improvement that is considered a hotfix or patch, then the release maintainer will apply to a branch `releases/1.x`, where `x` is the minor version they are patching.
|
| + |
They can then tag a new patch release, while also creating a `CHANGELOG` entry that is patched to the `master` branch – describing the changes in the patch release.
|
| + |
|
| + |
Note that these versions only apply to the versions of the binary releases.
|
| + |
For the crates in `heartwood`, we will use `cargo-semverchecks` to detect version changes and release the crates every 2 weeks.
|
| + |
We will start to explore tools like `cargo-release` and/or `cargo-smart-release` for making the process of releasing the crates easier for the team.
|
| + |
|
| + |
If you have any further suggestions, please reach out to us on [Zulip]!
|
| + |
|
| + |
### Yanking `iris` and `rosa`
|
| + |
|
| + |
The Radicle run seed nodes, `rosa.radicle.xyz` and `iris.radicle.xyz`, are set up to be permissive nodes in the network.
|
| + |
This has been a great experience for users coming to Radicle for the first time.
|
| + |
They immediately have nodes that replicate their projects.
|
| + |
Another benefit of this is that we are able to see how permissive nodes behave and can inspect their logs more easily.
|
| + |
|
| + |
That being said, they are nonetheless a maintenance burden that we, as a team, do not want to maintain forever.
|
| + |
|
| + |
Going forward, we will be working on reducing how permissive these nodes are.
|
| + |
Part of this work relates to [bootstrapping] as well as [policy improvements].
|
| + |
We will use these nodes to test these features and slowly, but surely, remove them from the network.
|
| + |
Do not worry, we will give ample time and plenty of announcements on more concrete timelines for when this will be underway.
|
| + |
|
| + |
## Protocol & Node
|
| + |
|
| + |
Now for the juicy parts.
|
| + |
Over the past few months, the team has been chipping away at a few larger topics regarding the protocol and the `radicle-node`.
|
| + |
On top of this, we also met in Helsinki recently and discussed a few potential topics for the roadmap.
|
| + |
Below are the bigger topics that generally touch the protocol and the node.
|
| + |
|
| + |
### Identity and Multi-Device
|
| + |
|
| + |
These topics are on the mind of every maintainer, contributor, and user of Radicle.
|
| + |
They are closely related but can be thought of as two different beasts.
|
| + |
On the one hand, multi-device would mean that any user of Radicle could work across multiple devices without any issues.
|
| + |
This includes using the same key on two different devices (looking at you YubiKey holders), or associating different keys to the same person.
|
| + |
The latter begins to sound a lot more like identity, where one person is not identified by a single key, and should be able to move that identity around with them.
|
| + |
|
| + |
Currently, when someone comes to the Radicle protocol and runs `rad auth` this generates their signing key.
|
| + |
This is used in a myriad of ways:
|
| + |
|
| + |
- The public portion of the key is used as the Node ID
|
| + |
|
| + |
- Which, in turn, is used as part of protocol handshakes
|
| + |
|
| + |
- It also identifies your namespace within a Radicle repository, e.g. `refs/namespaces/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/refs/heads/main`
|
| + |
|
| + |
- The current DID being used is `did:key` which is derived from the signing key
|
| + |
|
| + |
- The signing key is, naturally, also used for signing data including:
|
| + |
- `rad/sigrefs` – to tell the network that this the state of your Git references
|
| + |
- Changes to collaborative objects
|
| + |
- Announcements, which can be verified by other nodes to ensure that the message came from you
|
| + |
|
| + |
You may notice that this closely ties a node's identity to a user while also mixing the responsibility of the user signing data and the node signing data.
|
| + |
|
| + |
As you can see, while these decisions got us up and running quicker, it has come with consequences.
|
| + |
On top of this, we declared a 1.0 for the protocol, and so we have a duty to attempt to transition towards identity in a backwards-compatible way.
|
| + |
|
| + |
One of our main tasks will be to slowly provide a separation from the node's key and the user's key.
|
| + |
Some of this work is already underway and is happening with backwards-compatibility.
|
| + |
This may help us towards a story of multi-device, but we still have some constraints around signing references that blocks us on that front.
|
| + |
|
| + |
Our other task will be exploring key management systems (KMS) for allowing us to revoke and rotate keys of a user.
|
| + |
The astute reader will notice that `did:key` does not provide a way to this – its a self describing DID method, and so it *cannot* provide these functionalities.
|
| + |
Currently, we are interested in two key management systems and exploring their functionality: [Keyhive] and [BetterSign].
|
| + |
However, the introduction of one of these systems is not as simple as plugging it in and getting key revocation and rotation.
|
| + |
We also need to plan how those operations play with the current data that we are signing.
|
| + |
Some harder questions need to be answered:
|
| + |
|
| + |
- How do we continue to verify historical data?
|
| + |
- How do we handle revoked data that has been signed by a compromised key?
|
| + |
- How do we evolve the Git namespaces when a new key is introduced?
|
| + |
- Can we do this in a backwards-compatible fashion?
|
| + |
|
| + |
Finally, we want to provide a consistent identity for a person (or more generally an agent – no, not AI) that acts within the Radicle network.
|
| + |
For this, we have started to draft a [RIP][Agent Repository RIP] that describes a way for us to represent an identity that could be communicated using the Radicle protocol.
|
| + |
This draft needs to be further developed and tested with an implementation in the `heartwood` repository.
|
| + |
|
| + |
Admittedly, due to the size of these problems, the consequences of making these changes, and its lasting implications on the protocol we have moved a bit slower on this front.
|
| + |
It has, however, never been forgotten and we will continue to push towards an implementation for identity and multi-device.
|
| + |
|
| + |
### Migration of network I/O in `radicle-node` to `mio`
|
| + |
|
| + |
[Migration to mio]: #Migration-of-network-IO-in-radicle-node-to-mio
|
| + |
|
| + |
The crates [`netservices`], [`io-reactor`], and [`popol`] have served us well to implement `radicle-node`.
|
| + |
However, they are not ideal dependencies for ensuring long-term health of our network I/O layer:
|
| + |
- [`popol`] is only intended to support Unix-like platforms, and we are looking to support other platforms, like [Windows].
|
| + |
|
| + |
- Even though `io-reactor` defines the trait [`reactor::poller:Poll`] to potentially support multiple I/O polling mechanisms, there only is one single implementation for wrapping `popol`.
|
| + |
Issues for other polling crates are open since 2023 without tangible progress: [#10 for `mio`], [#9 for `polling`], [#8 for `epoll`].
|
| + |
This suggests that it is not a high priority for the maintainers to integrate with other polling abstractions (which might offer better cross-platform compatibility).
|
| + |
|
| + |
- The trait [`reactor::poller:Poll`] can only be implemented for file descriptors which also implement [`std::os::fd::raw::AsRawFd`] and this trait is only implemented on Unix-like platforms and WASI.
|
| + |
We believe that this is leaked from `popol`, as the only known implementation of the trait wraps it.
|
| + |
|
| + |
- We would like to benefit from network effects, i.e. from other people maintaining crates that depend on `io-reactor` to implement support for other pollers.
|
| + |
However, [according to crates.io, the only dependent is `radicle-node`][io-reactor-dependents] (via `netservices`).
|
| + |
Contrary to that, at the time of writing, [`mio` has 494 dependents according to crates.io][mio-dependents], and, notably, [`tokio`, which has 30628 dependents on crates.io, is dependent on `mio`][tokio-dependents].
|
| + |
We therefore think that even if `mio` is obsoleted, e.g. by [`a10`] (which is based on [`io_uring`] on Linux and could potentially build on top of [I/O rings on Windows]) the people behind a large network of dependent projects will come up with new ideas and solutions, that we would then benefit from.
|
| + |
|
| + |
- One downside of `mio` is that it forces the use of [`mio::Token`] to identify sources (while a type that is `Eq + Clone` might be enough), and that it forces the use of the types in [`mio::net`] for sockets, which need to be converted to/from [`std::net`] if required.
|
| + |
These distinctions are also [noted by cloudhead].
|
| + |
We are willing to buy in that far to `mio` to leverage the benefits of a well-tested and cross-platform network I/O layer.
|
| + |
|
| + |
A proof-of-concept is submitted as [patch `5ea90b97`].
|
| + |
|
| + |
### Windows Compatibility
|
| + |
|
| + |
[Windows]: Windows Compatibility
|
| + |
|
| + |
If we truly want Radicle to succeed, it is necessary that we attempt to provide the technology to as many people as we can.
|
| + |
This should include Windows users.
|
| + |
|
| + |
A pure Windows build of the `heartwood` repository has not been a number one priority for the team since we started.
|
| + |
The fact is that none of the team used Windows, with the majority of us on a flavour of Linux and a few MacOS users.
|
| + |
That did not stop some interested users on Windows coming along and asking questions!
|
| + |
|
| + |
More recently, a team member who has access to a Windows machine has started to slowly get some parts of the system working on Windows[^1][^2][^3].
|
| + |
This has allowed some interaction with Radicle via the `rad` CLI, and started paving the way to getting the `radicle-node` to also build.
|
| + |
To get to that, we need to make some changes to not rely on Unix specific utilities and take control of the underlying networking libraries and house changes to them within `heartwood` – with a draft patch already in place (See [Migration to mio]).
|
| + |
|
| + |
We also want to ensure that once we have Windows compatibility in place, that we do not easily lose it.
|
| + |
We will move towards testing more strictly in CI and have a target that checks the builds on Windows.
|
| + |
This will place Windows as a "second tier" platform within our ecosystem – meaning we will try support it, but it will not always be our first priority.
|
| + |
|
| + |
### Road to a Sans-I/O Protocol
|
| + |
|
| + |
While diving deeper into the `radicle-node` protocol, we realised that we were finding it hard to understand and modify the innards of the protocol code.
|
| + |
The logic of what happens in the protocol was tied to the I/O of calling to the network, modifying sqlite databases, etc.
|
| + |
At that point, we decided that it was time to explore [Sans-I/O].
|
| + |
|
| + |
This effort has already begun.
|
| + |
The first step was moving the majority of the code from `radicle-node` into a new `radicle-protocol` crate.
|
| + |
This kept the majority of the code as-is, but removed any dependencies on any crates that were required to perform I/O.
|
| + |
These were plugged in via `radicle-node`.
|
| + |
This was only the beginning.
|
| + |
|
| + |
To better understand these techniques, we have also made efforts to separate "business logic" away from I/O in smaller components of our code base.
|
| + |
This has been a great process and has resulted in code that is easier to reason about *and* easier to test.
|
| + |
This may be obvious to most people, but sometimes as programmers, we cut corners to get to a result faster – and one of those corners is mixing our business logic with I/O.
|
| + |
|
| + |
We have already started working towards a sans-I/O [implementation of the protocol][Sans-I/O Patch].
|
| + |
We have been dissecting the code that is in `radicle-protocol`, and finding components that have a single responsibility.
|
| + |
These components are being defined using an event and command architecture.
|
| + |
These components will then be composed to have an architecture that can be driven by commands and will output events – which can then be logged, made into metrics, notify the user, etc.
|
| + |
|
| + |
Once this has been sketched and tested, we plan on having a version of `radicle-node` that uses this version of the protocol and ensure that it has compatibility with the previous version.
|
| + |
|
| + |
From this point on, we will aim to explore how this helps us improve the protocol.
|
| + |
We will explore the possibility of new protocol messages, and better error handling for Git fetches.
|
| + |
As well as this, we want to explore different networking libraries such as [`iroh`] and [`libp2p`].
|
| + |
|
| + |
### Policy Improvements
|
| + |
|
| + |
[policy improvements]: #policy-improvements
|
| + |
|
| + |
The team was thinking about ways to improve node storage management and moderation.
|
| + |
One of the team noted a mode of behaviour that could be implemented that was dubbed quarantining, at the time.
|
| + |
The basic idea is that a node could say it wants to fetch a repository but not advertise it as part of its own inventory.
|
| + |
Put another way, the repository is in storage, but it is not being announced to the network.
|
| + |
|
| + |
So, what is the value of this mode of operation?
|
| + |
Once this repository has been fetched, it means that it can be inspected to evaluate whether the node operator wishes to announce it as part of the node's inventory.
|
| + |
If the repository is deemed worthy, then it can be promoted to be seeding, and if not, then it can be blocked.
|
| + |
|
| + |
Node operators can begin to ask questions like:
|
| + |
- How big is this repository?
|
| + |
- Can I detect illicit content in this repository?
|
| + |
- Are the delegates part of my follow list?
|
| + |
- Is this a Rust project?
|
| + |
- etc.
|
| + |
|
| + |
Essentially, this provides enough power to the operator, and the general ecosystem as a whole, to begin experimenting with their own kinds of moderation and node management.
|
| + |
|
| + |
The idea did not stop there.
|
| + |
As we tugged on this concept more, we started to compare it more to the existing behaviour.
|
| + |
The existing modes are "seed" and "block".
|
| + |
The former says that the node will fetch and announce the repository, while the latter says it will ignore it completely.
|
| + |
We were now proposing a mode that is only fetching, and we began to wonder about a mode that would only be announce.
|
| + |
After considering these different modes, potential use cases, and playing around with wording, we came to the conclusion that this concept seems to lie close to a [publish-subscribe] method.
|
| + |
The repository is a topic, fetching is subscribing, announcing is publishing, and we have the option to block the topic.
|
| + |
|
| + |
After this brief foray into thought, we have decided to formalise a RIP for improving policies and explore the implementation in `heartwood`.
|
| + |
The change to the node behaviour seems to be straight-forward, however, the CLI tooling and terminology seems to be the more challenging portion of this set of changes.
|
| + |
|
| + |
### Reaping Repositories
|
| + |
|
| + |
It has been a common occurrence that someone decides to try out Radicle, and they test it out on a repository – with an apt name, such as `radicle-test`[^4][^5][^6].
|
| + |
The next question on their mind is, "How do I delete this repository?"
|
| + |
They don't see an immediate answer in the set of `rad` commands, and they ask the same question in our [Zulip].
|
| + |
Unfortunately, up until this point, there has been no mechanism for deleting a repository.
|
| + |
|
| + |
Initially, we punted on it because in a decentralized network, you cannot go around to each machine and delete content – that would be censorship susceptible[^7].
|
| + |
After some thought, we decided that we could implement a mechanism where one could *ask* for their repository to be deleted.
|
| + |
|
| + |
The basis of this feature is to define a payload extension for the identity document, that could be added to set an expiry date for the repository.
|
| + |
Other nodes and node operators can then decide, based on the expiry, to reap the repository from their storage, and block it so that they would not replicate it again.
|
| + |
Essentially, if you wanted to delete the repository, then you would set the expiry to the current date-time and announce that to the network.
|
| + |
|
| + |
The aim for this feature is to provide this basic mechanism and supplement it with tooling through the `rad` CLI so that a node operator can easily detect expired repositories, and a user can ensure that their repository continues to live or die in the Radicle network.
|
| + |
|
| + |
### Bootstrapping
|
| + |
|
| + |
[bootstrapping]: #bootstrapping
|
| + |
|
| + |
To get things up and running, the Radicle team put together seed nodes – now called `rosa.radicle.xyz` and `iris.radicle.xyz` – that act as bootstrap nodes to the network.
|
| + |
This means that these nodes will relay gossip for new nodes that join the network.
|
| + |
When someone sets up a new node in the Radicle network, their Node ID and some other useful information well be gossiped to other nodes via the seeds.
|
| + |
|
| + |
We and other contributors feel that these nodes should not be necessarily defined as part of the `heartwood` repository.
|
| + |
The bootstrap process should be configured by the user, where the Radicle team can provide help and resources for picking nodes.
|
| + |
This can be a similar process to how Arch Linux users pick their mirrors for retrieving packages from.
|
| + |
This kind of work has already been [kicked off][Remove Bootstrap Nodes], but needs some more input to progress it further.
|
| + |
|
| + |
The aim of this is to encourage more decentralization of the network, allowing operators to act as bootstrap nodes in the future.
|
| + |
The team would slowly wind down the use of `rosa` and `iris` to reduce the maintenance burden of operating seeds as well as developing the protocol.
|
| + |
The road map for this process would be to remove them as predefined nodes in `heartwood`, and then slowly decommission them.
|
| + |
|
| + |
### Compatibility with Git Worktrees
|
| + |
|
| + |
The current setup of Radicle defines a directory where it stores repositories.
|
| + |
These repositories essentially contain the usual references that you interact with, each under [namespaces][Git Namespaces] of each node, as well as special references such as `rad/sigrefs` and collaborative objects, e.g. `xyz.radicle.patch`, `xyz.radicle.issue`.
|
| + |
This acts as the user's forge, where they can push and pull updates – using `git push` and `git fetch`, and interact with collaborative objects through the the `rad` CLI.
|
| + |
It's important to note, however, that they do this through a working copy of the repository – a non-bare repository which is a copy of the repository in storage.
|
| + |
|
| + |
There is a slight issue with this – it means you are duplicating the repository on your disk, and for very large repositories this could mean taking up to the range of 10's of gigabytes of disk space.
|
| + |
So, we asked ourselves, is there a way to unify these two repositories?
|
| + |
|
| + |
The answer, we believe, is [Git Worktrees].
|
| + |
The idea is that the Radicle storage would also be your working copy.
|
| + |
When you want to make changes to your namespace, then you would create a new worktree based on a reference that you want to work on top of, for example, the default branch of the repository.
|
| + |
|
| + |
To get to this point, we will need to improve certain aspects around reference handling, primarily with canonical references, and also teach our tooling to work better with bare Git repositories.
|
| + |
|
| + |
This will not only improve the storage space situation but may also feel more natural to some developers who prefer working with worktrees.
|
| + |
|
| + |
## Developer Experience
|
| + |
|
| + |
### Migrating Radicle CLI to `clap`
|
| + |
|
| + |
If you have been looking up `rad` options all the time, `clap` your hands!
|
| + |
We will start migrating our `rad` CLI command-line parsing over to the [`clap`] crate.
|
| + |
|
| + |
Up until this point, we have been using [`lexopt`] to parse command-line arguments.
|
| + |
The choice here was to have a small dependency that was flexible for defining our own help messages.
|
| + |
At the time, `clap` was going through its major rewrite and was moving towards the `v3.0.0` release.
|
| + |
|
| + |
While minimising dependency footprint is a useful endeavour, the team and contributors were feeling the pain of maintaining and hand writing out parsing logic for any and all of the CLI commands, using `lexopt`.
|
| + |
Last year, we did a spike on exploring `clap` to see if it could be useful for adding completions and providing dynamic hints, such as patch and issue identifier completions.
|
| + |
This gave us an idea of how using `clap` would work, but there was still some need for additional upstream changes back then, and ultimately the experiment was dropped for more pressing matters.
|
| + |
|
| + |
A while later, this was revisited again, and the main part of the exploration was checking if we could keep somewhat compatible help messages for the commands.
|
| + |
It was found that with some boilerplate, we likely could.
|
| + |
However, yet again, our attentions were diverted elsewhere.
|
| + |
|
| + |
Now, with enough interest in the change, we have picked the effort back up to bring this change over the finish line.
|
| + |
We hope to leverage all that `clap` brings with it: automatic argument parsing, completion tooling, a rich library experience, and an ever evolving ecosystem of tools around `clap` itself.
|
| + |
|
| + |
### Code Review Research
|
| + |
|
| + |
[Code Review Research][#code-review-research]
|
| + |
|
| + |
If you have been using Radicle for any amount of time, you will have likely used patches that are defined as part of the `rad` CLI, and the `git-remote-rad` [Git remote helper].
|
| + |
This is and has been the primary way of exchanging code changes via Radicle.
|
| + |
This has bought us a lot, allowing us to propose new changes and track the work that is going on through these patch contributions.
|
| + |
|
| + |
If you have been part of the Radicle [Zulip], you will have also noticed that maintainers of the `heartwood` repository tend to have discussions in the [#Patches] channel.
|
| + |
This is where we do the majority of our review.
|
| + |
We combine these discussions with creating `REVIEW` commits and pushing these as a new patch revision, for the original author to accept, modify, or drop.
|
| + |
|
| + |
On top of this, those who have dug around in the `rad patch` command will have noticed that `rad patch review --patch` and `rad patch review --hunk` seemingly have a flow for reviewing code.
|
| + |
These operations, unfortunately, were never wired up fully and are built on pieces of code that do not pan out with our underlying libraries.
|
| + |
Going forward, we intend to remove these options.
|
| + |
You may ask if this breaks backwards-compatibility, but we are of the opinion that if it didn't work in the first place, then there is nothing to be compatible with!
|
| + |
However, there are still ways to submit patch reviews, through [Radicle Desktop], a future release of [Radicle TUI], and `rad cob action` (this requires a bit more documentation for proper use).
|
| + |
|
| + |
Where does that leave us for code review?
|
| + |
We believe that this is a more complex and multifaceted problem, that requires a lot more thought and design.
|
| + |
Whole teams have gone into building tools that perform code review, e.g. Jane Street's Iron and Google's Gerrit.
|
| + |
Now take these problems and also add people who want use their own diff tools, crafted diff settings (e.g. diff algorithm), and still make sure it works in an environment of decentralized collaboration.
|
| + |
The landscape of tooling is also changing, where we see more and more users flocking towards [Jujutsu-VCS], where even some of our team are finding it useful for [their day-to-day][Jujutsu with Radicle].
|
| + |
The usage of `jj` seems to have even had a ripple effect of introducing change IDs into [Git itself][change-id commit footer]!
|
| + |
|
| + |
We are happy to start this research and start dropping down our ideas – but we're a small team.
|
| + |
This is somewhere where the whole community could really benefit by getting involved, researching these tools, and helping us build something that could be great.
|
| + |
Let's collaborate to improve collaboration! 🌱
|
| + |
|
| + |
### COB API Documentation
|
| + |
|
| + |
In the Radicle protocol, Collaborative Objects (COBs) play an important role in supplementing Git with social artifacts such as issues, patches and discussions, which are not inherently supported by Git.
|
| + |
It includes three predefined collaborative object types to support code collaboration: *Issues*, *Patches*, and *Identities*.
|
| + |
|
| + |
These COBs are primarily interacted with through their `rad` sub-commands, `issue`, `patch`, and `id` respectively.
|
| + |
However, the full set of interactions is not covered by these commands yet.
|
| + |
For example, there is no way to add a review comment using the `rad patch` command (see [Code Review Research]).
|
| + |
That does not mean that there is *no way* of doing this using the `rad` CLI.
|
| + |
There is a set of low-level, plumbing commands under `rad cob` that allow you to add COB actions for updating an object – note that for the `Identity` COB, these updates are not permitted, since we want strict validation of what can happen here.
|
| + |
With this in mind, we want to better document these commands and show how these actions can be used for modifying the objects, which means outside tooling can programmatically modify the objects by making CLI calls.
|
| + |
|
| + |
On top of this, we want to encourage more experimentation with COBs that can be defined by other contributors outside of the team, outside of the `heartwood` repository.
|
| + |
We will supplement the above documentation with further tutorials on how to define your own COBs and create your own workflows.
|
| + |
|
| + |
We plan to have all this information presented in a COB Guide on [radicle.xyz/guides][Guides], and we look forward to hearing about all the amazing COBs people will dream up!
|
| + |
|
| + |
### `rad` URI
|
| + |
|
| + |
A feature that we are missing in the Radicle ecosystem is being able to link to resources easily.
|
| + |
For example, there is no way to cross-link a patch to an issue saying that, when merged, the issue is solved – something that GitHub users have grown fond of.
|
| + |
|
| + |
Lorenz made an effort to kick-off discussion around this topic in a [RIP][Early URI Proposal] that linked to a notepad of rough notes on the topic.
|
| + |
Now, thanks to the effort of Richard Levitte (`levitte`), the topic has been revived in [another RIP proposal][`rad URI RIP`].
|
| + |
|
| + |
The goal here is to have a full specification of what the URI grammar looks like for identifying resources in Radicle, such as repositories, Git objects, and collaborative objects.
|
| + |
Applications can then use these URIs for linking to these resources within their application, users can have registered handlers for taking them to their preferred Radicle application, and we can begin to support automated workflows such as the one mentioned above with patches and issues.
|
| + |
With a mature scheme, we can also register it with [IANA][RFC 4395 – URI Scheme Registration].
|
| + |
|
| + |
<!-- Zulip -->
|
| + |
[Zulip]: https://radicle.zulipchat.com
|
| + |
|
| + |
<!-- Release Management -->
|
| + |
[How To Do Releases]: https://beyermatthias.de/how-to-do-releases
|
| + |
|
| + |
<!-- Identity and Multi-Device -->
|
| + |
[Keyhive]: https://www.inkandswitch.com/keyhive/notebook/
|
| + |
[BetterSign]: https://github.com/cryptidtech/bs
|
| + |
[Agent Repository RIP]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3trNYnLWS11cJWC6BbxDs5niGo82/patches/27fea5d31ad98a49b2b5b7520d196620c3ed2b92
|
| + |
|
| + |
<!-- Migration of network I/O in `radicle-node` to `mio` -->
|
| + |
[`netservices`]: https://crates.io/crates/netservices
|
| + |
[`io-reactor`]: https://crates.io/crates/io-reactor
|
| + |
[`popol`]: https://crates.io/crates/popol
|
| + |
[`reactor::poller:Poll`]: https://docs.rs/io-reactor/0.5.2/reactor/poller/trait.Poll.html
|
| + |
[#10 for `mio`]: https://github.com/rust-amplify/io-reactor/issues/10
|
| + |
[#9 for `polling`]: https://github.com/rust-amplify/io-reactor/issues/9
|
| + |
[#8 for `epoll`]: https://github.com/rust-amplify/io-reactor/issues/8
|
| + |
[`reactor::poller:Poll`]: https://docs.rs/io-reactor/0.5.2/reactor/poller/trait.Poll.html
|
| + |
[`std::os::fd::raw::AsRawFd`]: https://doc.rust-lang.org/nightly/std/os/fd/raw/trait.AsRawFd.html
|
| + |
[io-reactor-dependents]: https://crates.io/crates/io-reactor/reverse_dependencies
|
| + |
[mio-dependents]: https://crates.io/crates/mio/reverse_dependencies
|
| + |
[tokio-dependents]: https://crates.io/crates/tokio/reverse_dependencies
|
| + |
[`a10`]: https://crates.io/crates/a10
|
| + |
[`io_uring`]: https://en.wikipedia.org/wiki/Io_uring
|
| + |
[I/O rings on Windows]: https://learn.microsoft.com/en-us/windows/win32/api/ioringapi/
|
| + |
[`mio::Token`]: https://docs.rs/mio/1.0.4/mio/struct.Token.html
|
| + |
[`mio::net`]: https://docs.rs/mio/1.0.4/mio/net/index.html
|
| + |
[`std::net`]: https://doc.rust-lang.org/stable/std/net/index.html
|
| + |
[noted by cloudhead]: https://cloudhead.io/popol/
|
| + |
[patch `5ea90b97`]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/patches/5ea90b9757059522e80301bbd9b1458a39a71f7e
|
| + |
|
| + |
<!-- Windows Compatibility -->
|
| + |
[^1]: [radicle-cli: Build on Windows](https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az3gqcJUoA1n9HaHKufZs5FCSGazv5/patches/af3292c47ec93d906ccda8d9382f711c2201e678)
|
| + |
[^2]: [node: Use winpipe for control socket on Windows](https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az3gqcJUoA1n9HaHKufZs5FCSGazv5/patches/5109cda98885b00c1d4f7165013e4d66f9b7512f)
|
| + |
[^3]: [radicle/profile: Control socket path for Windows](https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az3gqcJUoA1n9HaHKufZs5FCSGazv5/patches/c7498dcdee66fbca673c7d6b85dfc18555fbd988)
|
| + |
|
| + |
<!-- Road to Sans-I/O Protocol -->
|
| + |
[Sans-I/O]: https://sans-io.readthedocs.io/
|
| + |
[Sans-I/O
|
| + |
Patch](https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/patches/511ad5ad569fea9124a9ad4738431e42b5075675)
|
| + |
[iroh]: https://www.iroh.computer/
|
| + |
[libp2p]: https://libp2p.io/
|
| + |
|
| + |
<!-- Policy Improvements -->
|
| + |
[publish-subscribe]: https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern
|
| + |
|
| + |
<!-- Reaping Repositories -->
|
| + |
[^4]: https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az23FUbgvSZMtshnoYuxmvaHfgMsCe
|
| + |
[^5]: https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az2H5Cae9kLahf57MbYoipimZzF2VU
|
| + |
[^6]: https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az2KGZouSGAtbVcK4wkpWJP3MXSK3h
|
| + |
[^7]: One of the tenets of the Radicle protocol is to offer censorship resistance.
|
| + |
|
| + |
<!-- Bootstrapping -->
|
| + |
[Remove Bootstrap Nodes]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/patches/3219ef871dd44c7ef51693f4aeba4c2c5c0c5c7b
|
| + |
|
| + |
<!-- Compatibility with Git Worktrees -->
|
| + |
[Git Namespaces]: https://git-scm.com/docs/gitnamespaces
|
| + |
[Git Worktrees]: https://git-scm.com/docs/git-worktree
|
| + |
|
| + |
<!-- Migrating Radicle CLI to clap -->
|
| + |
[clap]: https://crates.io/crates/clap
|
| + |
[lexopt]: https://crates.io/crates/lexopt
|
| + |
|
| + |
<!-- Code Review Research -->
|
| + |
[Git remote helper]: TODO
|
| + |
[#Patches]: https://radicle.zulipchat.com/#narrow/channel/383670-Patches
|
| + |
[Radicle Desktop]: https://desktop.radicle.xyz/
|
| + |
[Radicle TUI]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z39mP9rQAaGmERfUMPULfPUi473tY
|
| + |
[Jujutsu-VCS]: https://jj-vcs.github.io/jj/latest/
|
| + |
[Jujutsu with Radicle]: https://radicle.xyz/2025/08/14/jujutsu-with-radicle
|
| + |
[change-id commit footer](https://lore.kernel.org/git/CAESOdVAspxUJKGAA58i0tvks4ZOfoGf1Aa5gPr0FXzdcywqUUw@mail.gmail.com/)
|
| + |
|
| + |
<!-- COB API Documentation -->
|
| + |
[Guides]: https://radicle.xyz/guides
|
| + |
|
| + |
<!-- rad URI -->
|
| + |
[Early URI Proposal]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3trNYnLWS11cJWC6BbxDs5niGo82/patches/19ba16634fbde97156255ed97069d0aa3ab2bf12
|
| + |
[`rad` URI RIP]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3trNYnLWS11cJWC6BbxDs5niGo82/patches/2e2061857d703b8467648ff2b77efd61c72ca583
|
| + |
[RFC 4395 – URI Scheme Registration]: https://www.rfc-editor.org/rfc/rfc4395.html#section-5
|