# Radicle User Guide
[TOC]
# Introduction
Software is *the* fundamental way in which we interface with data that comprises our current reality, and code is the language of software. Most software systems were created through a collaborative process involving multiple people. If we accept that software is important and collaborative by nature, then a shared system for communicating about code and collaborating is needed. This system shouldn't be owned by one company, as code is too important to be monopolized.
---
<small>
`๐Learn more:`
Microsoft acquired GitHub in 2018. They also own 49% of OpenAI. One of our prophets of the future, the author Philip K. Dick, has shown us many projections of alternate dystopian realities that emerge when corporations amass too much power. While some may question the reliability of his visions as he was often fueled by substances that would make even psychonauts raise an eyebrow, consider this: the Oracle at Delphi's officiant claimed to glimpse through the veil by inhaling naturally occurring gasses emerging from the ground.
</small>
---
Furthermore, our world is increasingly polarized, and this reality is finding its way into software companies and therefore into software products. Users are banned from using a platform because of their geographic location or the ideas they stand for. This is not tenable.
This is why weโve created Radicle, an open protocol that enables users like you to collaborate on your code within a sovereign network. It's a neutral environment where you have full ownership of your data and you have the autonomy to set the rules of your code universe as you see fit. You can work on software projects (and ultimately more) even when offline, while also being connected to a broader network, through which you'll eventually be able to find contributors.
We've created this Radicle Guide to initiate you as a settler of our network through teaching you how to use the client software we've developedโthe Radicle CLI, which is both a node and command line interface tool for interacting with the protocol. This guide is split into multiple chapters and we recommend starting with the first chapter for a higher level introduction that takes you on a tour through Radicle's core functions. Subsequent chapters will provide deeper dives into specific use cases, but they are still in progress.
---
<small>
`๐พ Radlien Tip:`
If you ever get stuck and want additional guidance, join us in our [chatroom on Zulip](https://radicle.zulipchat.com/) and ask your questions in the support channel.
Also, this guide teaches you how to use Radicle in a narrative fashion, inspired in part by [Why's Poignant Guide to Ruby](https://poignant.guide/). If you're looking for more straightforward usage docs, check out the [Radicle Manual](#), or also check out the [Protocol Overview](#) for more information on our fundamental building blocks and motivations.
Oh! And allow me to introduce myself. My name is Radlien and every once in a while you may see me in this guide, interjecting with hot tips like this.
</small>
---
## Index
- Chapter 1: Getting started with Radicle
- Setting up an identity, playing around with a few common commands to familiarize yourself with the cli, adding one of your already existing Git repositories on your machine to the Radicle network, using the cli with the webapp.
- Chapter 2: Collaboration with issues & patches
- rad issue, rad patch, rad remote, rad checkout
- Chapter 3: Seeding policies & seed nodes
- seed, unseed, follow, unfollow, blocking
- Chapter 4: Delegates & repository identity
- repo id updates, delegates
- Chapter 5: p2p node replication sync
- node, sync, config
- Chapter 6: Radicle's internals.
- Understanding the storage layout, file system, COBs and logs.
- Browsing through storage, running "rad cob" to see underlying objects, reviewing node logs to see what the node is doing.
---
# Chapter 1: Getting Started with the Radicle CLI
One of the important facts to understand about Radicle is that it is a peer-to-peer protocol, which is uncommon when it comes to software you typically rely on. Most collaboration technologies are hinged upon a client-server model, where you're entrusting your data and social interactions to a single corporation that is managing a bunch of servers or data centers. This paradigm is transformed in a peer-to-peer protocol, where every user of the protocol is also technically a server. Peers on the Radicle network are also referred to as **nodes**, and it doesn't matter what you are doing -- whether you're publishing repositories or creating an issue -- you have to operate a node.
Within a few paragraphs, you'll be operating a Radicle node via the command line by installing the client software we've developed: the Radicle CLI. Today, this is the only way you can interact with the protocol. Interface-fiends fear not, we have a supplementary web app. But regardless, you have to install the Radicle CLI and set up your node if you intend to do more than browse. It's a pretty easy process to set up a node that can be completed in under 5 minutes, but there are a few requirements that are important to run through before you proceed:
1. You need a Linux or Unix based operating system like macOS and a basic understanding of how to use your terminal.
2. Radicle is built on top of git, so a recent version of *git* (2.34.0 or later) has to be installed. We also assume you have experience using git.
3. OpenSSH (version 9.1 or later) with `ssh-agent` has to also be installed and running. This is helper program used to encrypt and securely access the secret key related to your Radicle identity.
---
<small>
`๐พ Radlien Tip:`
If you're a Windows user, we are sorry if we've wasted your time, I hope you've at least become intrigued by Mentharos, who is from the same planet as me, Neborea.
You can check your git and ssh installations by running `git --version` or `ssh -V` in your terminal.
Wat is Git and ssh-agent, u wonder?
**[Git](https://en.wikipedia.org/wiki/Git)** is a distributed version control system that manages and tracks changes in computer files, predominantly used for source code and collaborative programming. If you haven't used git before, you're going to be in a world of pain and should read through the [Pro Git](https://git-scm.com/book/en/v2) book first.
</small>
---
The easiest way to install Radicle is by firing up your terminal and running the following command:
```
$ sh <(curl -sSf https://radicle.xyz/install)
```
This command runs an installer script that automates the setup process by:
- Identifying your OS and installing Radicle binaries suitable for your system, including `radicle-remote-helper`, `radicle-cli`, `radicle-node`, and `radicle-httpd`, all placed in `~/.radicle/bin`. This is a non-standard location, so the script also updates your `PATH` variable to include the path to these binaries.
- Installing manuals to `~/.radicle/man`, which enables you to access usage documentation for the cli through `rad help` or `rad <command> --help`.
---
<small>
`๐พ Radlien Tip:`
If you want the above to be installed in a different location than `~/.radicle`, then you can set the variable `RAD_HOME` before running the script.
Note that if you don't want to use the installer script, you can also always compile from the [source code](https://app.radicle.xyz/seeds/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5), or get the [binaries](https://files.radicle.xyz/latest/) if you prefer.
</small>
---
Once you've installed Radicle, you can make sure that it was successful by running the `rad` base command:
```
$ rad
```
You should see an output like this, which includes a list of common sub-commands:
```
rad 0.8.0 (59f506db)
Radicle command line interface
Usage: rad <command> [--help]
Common `rad` commands used in various situations:
auth Manage identities and profiles
checkout Checkout a project into the local directory
clone Clone a project
fork Create a fork of a project
help CLI help
id Manage repository identities
init Initialize a project from a git repository
inspect Inspect a radicle repository
issue Manage issues
ls List projects
node Control and query the Radicle Node
patch Manage patches
path Display the radicle home path
clean Clean a project
self Show information about your identity and device
seed Manage repository seeding policies
follow Manage node follow policies
unfollow Unfollow a peer
remote Manage a project's remotes
sync Sync repositories to the network
See `rad <command> --help` to learn about a specific command.
```
## Come into being from the elliptic aether
When using Radicle for the first time, you have to create a new Radicle identity, which is simply a cryptographic key pair (a public key and secret key). The public key is what uniquely identifies you across the network, while the secret key is used to authenticate your node, as well as sign code and other artifacts you publish to the network.
---
<small>
`๐Learn more:`
A cryptographic key pair is a set of two keys used in cryptography, typically for securing digital communication and data. The pair consists of a public key and a private (or secret) key. The public key can be shared with others and is used to encrypt data or verify digital signatures created with the corresponding private key. Conversely, the private key is kept secret by the owner and is used to decrypt data encrypted with the public key or to create digital signatures. The use of these keys ensures authenticity, as digital signatures can confirm that a message or data was indeed sent by the owner of the private key.
</small>
---
See the `auth` sub-command displayed in the prior output? That's how you'll cryptographically forge your idenity. Simply run:
```
$ rad auth
```
Follow the instructions by entering an **alias**, a non-unique name that makes it easier to identify your node, in addition to a **passphrase** to protect your key pair. Note that your alias can always be changed at a later time.
```
$ rad auth
Initializing your radicle ๐พ identity
โ Enter your alias: Radlien
โ Enter a passphrase: ********
โ Creating your Ed25519 keypair...
โ Adding your radicle key to ssh-agent...
โ Your Radicle DID is did:key:z6Mkhp7VUnuufpvuQ3PdysShAjL86VDRUpPpkesqiysDBGs9. This identifies your device. Run `rad self` to show it at all times.
โ You're all set.
To create a Radicle repository, run `rad init` from a Git repository with at least one commit.
To clone a repository, run `rad clone <rid>`. For example, `rad clone rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5` clones the Radicle 'heartwood' repository.
To get a list of all commands, run `rad help`.
```
When you've completed the steps, your new Radicle DID (Decentralized Identifier) will be generated and displayed. Basically what this did was create an Ed25519 keypair that you can now use, adding your secret key to `ssh-agent`.
If you run `rad auth` again you can verify that your key was added to `ssh-agent`.
$ rad auth
โ Radicle key already in ssh-agent
---
<small>
`๐Learn more:`
The `ssh-agent` is a helper program that manages your SSH keys and passphrases, encrypting the keys with your passphrase for secure storage. Once the keys are loaded into the agent, it can use them to authenticate your access to Radicle and sign data, eliminating the need to re-enter your passphrase. Use `ssh-add -l` to view the keys the agent currently holds. For further details, visit https://www.ssh.com/academy/ssh/agent.
</small>
---
Your Radicle DID is quite similar to your Node ID (NID), the main difference is the DID has the prefix `did:key:` which is the component that makes the identifier a **Decentralized Identifier**. Share your Radicle DID freely with collaborators.
---
<small> `๐ Learn more:`
**DIDs** are a new identifier standard established by the W3C that are used for interoperability across various systems and provide flexibility for incorporating different types of identifiers in the future.
**Ed25519** is a public-key signature system that uses a variant of the Schnorr signature based on Twisted Edwards curves. It's known for its speed, security, and efficiency, and is used in applications like SSH authentication, TLS encryption, and software package verification.
</small>
---
If you forget your DID or NID, you can query your full identity by running `rad self` or alternatively you can grab your DID with `rad self --did` and your NID with `rad self --nid`.
```
$ rad self
```
This displays your alias, DID, Node ID, SSH agent status, SSH keys, and the locations of important files or directories.
```
$ rad self
Alias paxel
DID did:key:z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C
โโดNode ID (NID) z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C
SSH running (?)
โโดKey (hash) SHA256:YCmRe6BkDOp45lYg0m5DeYxgRcPKftQZb4RmQD1nkjQ
โโดKey (full) ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO9xo9DHlsZJeZWnZaaawsnKFjcQxN4LQโฆ
Home /Users/paxel/.radicle
โโดConfig /Users/paxel/.radicle/config.json
โโดStorage /Users/paxel/.radicle/storage
โโดKeys /Users/paxel/.radicle/keys
โโดNode /Users/paxel/.radicle/node
```
---
<small>`๐พ Radlien Tip:`
Many of the other items you see in the `rad self` output can be viewed individually. Wondering about your alias? A quick `rad self --alias` has you covered. Need to pinpoint your home folder? `rad self --home` is your friend. And for your config file location, just hit up `rad self --config`. If you're ever feeling lost, `rad self --help` will lay out all your options.
</small>
---
## Operate nodes, smoothly
*RUReady to become a (smooth) node operatooor
Host to host, repo to repo, don't need your email
NAT traversing across nodes, where the storage is yours
(smooth) node operatooors*
Now that your node has an identity (or 'public key'), you have what it takes to connect to Radicle. That's right -- we don't need your email address or any other personal identifying information. Your alias can be your cat's name for all we care.
The first command to embed deep within your consciousness is the one for checking your node's status:
$ rad node status
If the node is not running, you can start it as a background daemon with:
$ rad node start
After your node starts, it will attempt to connect to peers on the network.
But let's take a step back and ponder a fundamental question: *What exactly happens when these nodes interact, and I hear Radicle was built on Git -- how does that fit into this picture?*
At its core, Radicle marries the robust, tried-and-true practices of Git with the sovereign world of peer-to-peer networking. Your node isn't just another cog in the machine; it's a conduit for collaboration. Its raison dรชtre? **To host and synchronize Git repositories you're interested in**.
Radicle's peer-to-peer architecture draws inspiration from Scuttlebutt's gossip protocol where data transmission relies on a publish/subscribe system, allowing peers to host and sync only the data they care about. Similar to BitTorrent, we use the terminology "seeding" to describe distributing and sharing a repository across the network.
With Radicle's gossip protocol, peers exchange messages to and from routing tables that facilitate the discovery and replication of repositories. The replication process kicks off when a node establishes a secure connection with one or more seeds of a repository after receiving a message about a repository update. Following this, the node conducts a `git-fetch` operation via the Git protocol to pull the pertinent Git objects into the nodeโs storage, thereby availing them to other interested nodes.
Note that a node joining the network for the first time will not know of any peers, so the Radicle CLI has been pre-configured to automatically connect to two *bootstrap nodes*. These are `seed.radicle.garden` and `seed.radicle.xyz`, which are registered DNS names that resolve to node addresses on the network. In the *bootstrapping* process, your node resolves these names to have a set of initial addresses to connect to, and once they establish connection with a peer, use a peer discovery process to find more peers.
*If you're curious to learn more about how Radicle works under the hood, read our [Protocol Guide](#).*
## Git going with repositories
We built Radicle on good old Git, the go-to for version control because, well, it is widely used and works extremely well. For a zeptosecond, we considered inventing a new system but heard a strong shout in our brains that said something like "YOU'D BE SO STUPID TO REINVENT VERSION CONTROL RIGHT NOW".
Sure, Git has its quirks, but isn't there a bit of beauty in imperfection? We're all about keeping things familiar, so we made sure Radicle plays nice with the tools you already use, including your favorite IDEs. It's all about making your coding life easier, without having to rewire your habits too drastically.
Now, time to return to your terminal. Navigate to your favorite public repository where you're the maintainer (it should have at least one git commit).
To publish it to the Radicle network, first ensure its a git repository with `git status`, and then run the `rad init` command.
```
$ cd dark-star-data
$ git status
$ rad init
```
Don't be afraid to do this on one of your existing public repositories! Because even if you aren't ready to use Radicle for code collaboration, it works great for distribution where you can establish a more decentralized "mirror" of your code, so to speak. A mirror that is *censorship resistant, sovereign, ungovernable -- except by you, and oh so magical*. Yada yada. You get the point ;)
What `rad init` does is gather the essential details from you which are needed to initialize the repository into Radicle: the repository name, description, default branch (typically `main` or `master`), and whether the visibility is public or private.
```
$ rad init
Initializing radicle ๐พ project in .
โ Name the-universes-matrix
โ Description Decoding data from the dark star to establish a model of the universe.
โ Default branch main
โ Visibility public
โ Project the-universes-matrix created.
Your project's Repository ID (RID) is rad:z31hE1wco9132nedN3mm5qJjyotna.
You can show it any time by running `rad .` from this directory.
โ Project successfully announced to the network.
Your project has been announced to the network and is now discoverable by peers.
You can check for any nodes that have replicated your project by running `rad sync status`.
To push changes, run `git push`.
```
Similar to how `init` is used to initialize a git repository, we use nomenclature you're familiar with so you don't go crazy. That'd be so cruel if you had to do `rad new`, instead, wouldn't it?
After entering your repository details, you're presented with a Repository Identifier (RID) that is a globally unique URN that you share with your collaborators so that they can clone your repository, e.g. `rad:z31hE1wco9132nedN3mm5qJjyotna`. Besides generating the RID, all this command does is create a special git remote in your working copy named `rad` and publishes the repository to the network, assuming it's public. We'll talk more about private repositories in another chapter.
---
<small>
`๐Learn more:`
A [URN or Uniform Resource Name](https://en.wikipedia.org/wiki/Uniform_Resource_Name) is a Uniform Resource Identifier (URI) that uses the `urn` scheme. URNs are globally unique persistent identifiers assigned within defined namespaces so they will be available for a long period of time, even after the resource which they identify ceases to exist or becomes unavailable.
</small>
---
When you initialize a repository you are the sole maintainer or *delegate*, the term we use in Radicle -- okay maybe we do want to drive you slightly crazy? Just kidding, we call them *delegates* because since these are simply public keys, who or what they belong to is very flexible. A key could belong to a group, or even a bot. It doesn't have to be just an individual "human maintainer".
---
<small>`๐พ Radlien Tip:`
A few hot commands you might wanna know about, that can be run within a repository you've initialized:
- It's difficult to memorize RIDs. You can always display it again with the command `rad .`
- To display the repository's identity payload, which contains its name, description and default branch by running `rad inspect --payload`.
- To make updates to the repository identity, including it's visibility, check out `rad id --help` for further instructions.
</small>
---
Note that your new repository will only be replicated by nodes that you are connected to and either have an open seeding policy, or trust your Node ID. Seeding involves both hosting the repository and synchronizing changes with other nodes. In the early stages of the Radicle network, all public repositories are automatically seeded by `seed.radicle.garden` which is both a *bootstrap node* and a *public seed node*.
Seed nodes are always-on machines that significantly enhance the networkโs capacity to provide continuous access to one's repositories. They can vary in their seeding policies, from public seed nodes like `seed.radicle.garden` that openly seed all repositories to community seed nodes that selectively seed repositories based on rules established by the node operator(s).
---
<small>
`๐พ Radlien Tip:`
You may be wondering -- Seed nodes?! Servers I'm automatically connected to!? Hrmmp. How is this any different than GitHub?
Well -- you don't have to trust or rely on our public seed node. You can run your own! As more people run them, Radicle becomes more resilient and reliable for code collaboration. We are always looking to attract more people that want to operate public seed nodes: if that's you, check out our [Seeder's Guide](#) for more details.
</small>
---
## Publishing ch-ch-ch-ch-changes
<small>
*Still don't know what I was waiting for
Requiring an internet connection to push to remote
But now I push to my local-first, oh so `rad` remote
Instead of that one shoddy monopolized forge*
</small>
As we just mentioned, `rad init` creates a special remote in your working copy named `rad`. What's this doing under the hood? With Radicle, you will typically be interacting with two different repository copies on your device, the *working copy* and a hidden, *stored copy* that you interact with via `git push rad` and `git pull rad` commands using Radicle's *git remote helper* program named `git-remote-rad`. Remote helpers are particularly useful for integrating Git with specialized network protocols like Radicle. Git calls the custom `git-remote-rad` program when it encounters `rad://` remotes.
---
<small>
`๐Learn more:`
Git remote helpers are custom programs that allow Git to interact with repositories hosted on various types of servers or protocols that are not natively supported. Remote helpers are invoked by Git when it encounters a URL scheme that matches a supported helper. For example, in Radicle's use case, if Git sees a URL starting with `rad://`, it will look for a remote helper program named `git-remote-rad` and use this program to handle operations related to that URL, such as fetching, pushing, and cloning. For more details, check out [Git's docs](https://git-scm.com/docs/gitremote-helpers).
</small>
---
To view information about the `rad` remote that was just created, try running `git remote show rad`.
```
$ git remote show rad
```
Here, for the fetch URL you see the repository's URN in a URL format: `rad://z31hE1wco9132nedN3mm5qJjyotna`. For the Push URL, you may be wondering, what is the element after the slash, `z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C`? Does it look familiar to you? Well, it's my Node ID. You should see your Node ID there for your `rad` remote.
```
$ git remote show rad
* remote rad
Fetch URL: rad://z31hE1wco9132nedN3mm5qJjyotna
Push URL: rad://z31hE1wco9132nedN3mm5qJjyotna/z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C
HEAD branch: (unknown)
Remote branch:
main tracked
Local branch configured for 'git pull':
main merges with remote main
Local ref configured for 'git push':
main pushes to main (up to date)
```
When using git with traditional forges, you are pushing to a remote which is a common centralized server that all other collaborators are also pushing to. But in Radicle, the remote is on your device & local-first which means that you can push changes even when you're disconnected from the internet. Changes that you push to the remote will automatically propagate to the network once you reconnect. This is one of the very unique aspects of Radicle's design that makes offline work a more *smooth operation*. ๐พ
Radicle's storage layout accommodates multiple repositories and peers per repository. Each repository is a bare Git repository, residing under a common base directory, uniquely identified by its Repository ID (RID). Rather than storing peer data in separate Git repositories with individual object databases (ODBs), Radicle consolidates peer data within the same Git repository. This is achieved using the `gitnamespaces` feature, where each peer's unique Node ID serves as a namespace to differentiate their Git objects.
Now let's try publishing some changes to see how this works.
Use your favorite text editor to make a change to the repository that you just initialized. For example, you can update its README.md file to include instructions on how to clone the repository with Radicle. Once you're finished, add and commit your changes with `git add` and `git commit` just as you would when collaborating on any other git-based forge. Then use `git push rad main` to synchronize changes across the working and stored copies of your repository (be sure to replace `main` with your branch name, in case that's not it).
```
$ echo "Seeded on Radicle. Install the Radicle CLI (https://radicle.xyz/#try) then clone with `rad clone rad:z31hE1wco9132nedN3mm5qJjyotna`" >> README.md
$ git add .
$ git commit -m "Update readme"
$ git push rad main
โ Synced with 1 node(s)
To rad://z31hE1wco9132nedN3mm5qJjyotna/z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C
ecb1bf0..74fb8d2 main -> main
```
Whenever you execute a `git push rad` command, you are pushing the changes on your local working copy to your remote copy. You see that the remote of your repository is represented by the URL `rad://z31hE1wco9132nedN3mm5qJjyotna/z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C` and it has a new commit hash that represents the current state of the repository.
As the sole delegate of the repository, changes that you push to the repository's default branch on your node represent the *canonical* or *authoritative* state of the repository. This means that if someone clones your repository, they would always be cloning the same commit hash represented by the remote of your node.
---
<small>
`๐Learn more:`
The canonical repository version is established *dynamically* based on the delegate thresholds defined for the repository. For example, if a `threshold` of two out of three delegates is set, with the `defaultBranch` specified as `main`, and both Alice and Bob have the same commit in their `main` branches, that specific commit is recognized as the authoritative, current state of the repository. In the current Heartwood release, the dynamic establishment of an authoritative version is limited to a single `defaultBranch`. Future releases of the protocol may enhance this feature to include additional secondary branches for dynamic authoritative versioning.
</small>
---
You may be wondering -- now that you've pushed to your remote, how do other peers get this update? Any peer who has cloned or seeded the repository will receive a *reference announcement* message from the gossip protocol, which informs the node there was an update. Following this, peers conduct a `git-fetch` operation via the Git protocol to pull the pertinent Git objects into their storage, thereby making them available to other interested nodes.
## The basics of seeding and cloning
Nodes have a *seeding policy* which specifies the list of repositories they are interested in seeding, in addition to retention rules. This means that nodes aren't just seeding random repositories, users have an active choice in deciding the repository data on their device.
There are a few ways that seeding relationships are established among nodes. One of the main methods is by one node intentionally *cloning* another repository. You can run the `rad clone` command to clone a repository from the Radicle network, by supplying a Repository Identifier (RID).
Let's try this out. First, navigate to your directory where you typically clone git repositories. Then run this command to clone the Radicle heartwood repository:
$ rad clone rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
---
<small>
`๐Learn more:`
Heartwood is the name of the current iteration of the Radicle protocol. An alpha version was initially released in April 2023.
</small>
---
Cloning has some similarities to `git-clone` such that it creates a working copy, but this is executed in a much different way since Radicle is a peer-to-peer network. It is equivalent of running these commands:
- `rad seed`: updates your seeding policy to make your node a seed of the repository
- `rad sync --fetch`: fetches the latest repository data from other seeds and stores it in your local storage
- `rad checkout`: creates a working copy of the repository from local storage
- `rad remote add`: creates a `rad` remote setup that your working copy can pull from and push to.
```
$ rad clone rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
โ Seeding policy updated for rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 with scope 'all'
โ Fetching rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 from z6Mkk4RโฆSBiyXVM..
โ Fetching rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 from z6Mksmpโฆ1DN6QSz..
โ Fetching rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 from z6MkrLMโฆocNYPm7..
โ Creating checkout in ./heartwood..
โ Remote cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT added
โ Remote-tracking branch cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT/master created for z6MksFqโฆbS9wzpT
โ Repository successfully cloned under /Users/<username>/git/heartwood/
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ heartwood โ
โ Radicle Heartwood Protocol & Stack โค๏ธ๐ชต โ
โ 8 issues ยท 14 patches โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
Run `cd ./heartwood` to go to the project directory.
```
When you only want to seed the repository and have no interest in contributing code, you can still be a repository's friend with the `rad seed` command alone! This is like our version of a more prosocial "starring", where you show a repository some real love and care by syncing its latest copy to your machine.
This works similar to cloning, where the RID is provided:
$ rad seed rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
When you seed a repository, it updates your seeding policy to subscribe to updates, it creates a copy of the repository under your local storage, and provides a replica to the network.
```
$ rad seed rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
โ Seeding policy updated for rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 with scope 'all'
โ Fetching rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 from z6Mkk4RโฆSBiyXVM..
โ Fetching rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 from z6Mksmpโฆ1DN6QSz..
โ Fetching rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 from z6MkrLMโฆocNYPm7..
```
In the future, if you change your mind and decide that you want to contribute code to a repository you're seeding alone, you can always run `rad checkout` to create a working copy of the repository from local storage and `rad remote add` to create a remote that you can pull from and push to.
If you only want to see repositories you've cloned or ones where you're a creator or delegate, omitting the repositories you're seeding alone, try `rad ls`. Alternatively, the command `rad ls --all` can be used to see all replicated and locally-available repositories, including the ones you are seeding. While `rad ls --seeds` will display *only* the repositories you're seeding.
```
$ rad ls
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Name RID Visibility Head Description โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ dark-star-data rad:zbJ72s765A35JCBqwXxxbMpFAWwv public d1fc2c6 Data supporting that the dark star is corruptinโฆ โ
โ heartwood rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 public c13c658 Radicle Heartwood Protocol & Stack โค๏ธ๐ชต โ
โ the-universes-matrix rad:z31hE1wco9132nedN3mm5qJjyotna public b1672f3 A matrix model of the universe โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
```
---
<small>
`๐พ Radlien Tip:`
- When cloning or seeding with the command defaults, your node will subscribe to updates from _all_ peers. This behavior is part of the seeding policy and can be changed by passing `--scope followed`, to only subscribe to updates from the repository delegates plus any node that is explicitly followed via `rad follow <nid>`. If a repository wasn't initially cloned or seeded in this way, it can also be changed later via the `rad seed` command, e.g. `rad seed rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 --scope followed`
</small>
---
## But what about web interfaces?
Radicle has definitely been optimized at this point for the CLI, but all projects published to Radicle are discoverable via a web client that is in beta. The current abilities are that you can browse projects from your local machine, create & discuss issues, and discuss patches.
The Radicle CLI is required to interact with the web client. First your node must be running. Open a new terminal window and check the status with `rad node status` and if it's not running, enter `rad node start`. Then you can use `rad web` to authenticate your local machine to interact with the interface:
```
$ rad web
```
This will open Radicle's web app located at `https://app.radicle.xyz` in your default browser. Note that you have to keep this terminal open and the command must be run from the same machine where the browser is being opened.
```
$ rad web
2024-01-30T18:52:36.678869Z INFO request{id=34002}: radicle_httpd: 127.0.0.1:52700 "GET /api/v1/sessions/OWzskDF2VLIcX9cfz21id5dfV2G46aLH HTTP/1.1" 200 OK 42.8ยตs 194
2024-01-30T18:52:36.680352Z INFO request{id=34003}: radicle_httpd: 127.0.0.1:53732 "GET /api/v1/node HTTP/1.1" 200 OK 654.914ยตs 492
2024-01-30T18:52:36.681859Z INFO request{id=34004}: radicle_httpd: 127.0.0.1:52700 "GET /api/v1/node HTTP/1.1" 200 OK 569.526ยตs 492
2024-01-30T18:52:36.682017Z INFO request{id=34005}: radicle_httpd: 127.0.0.1:52856 "GET /api/v1/sessions/OWzskDF2VLIcX9cfz21id5dfV2G46aLH HTTP/1.1" 200 OK 53.217ยตs 194
2024-01-30T18:52:36.683600Z INFO request{id=34006}: radicle_httpd: 127.0.0.1:53732 "GET /api/v1/node HTTP/1.1" 200 OK 791.585ยตs 492
2024-01-30T18:52:36.683730Z INFO request{id=34007}: radicle_httpd: 127.0.0.1:52856 "GET /api/v1/sessions/OWzskDF2VLIcX9cfz21id5dfV2G46aLH HTTP/1.1" 200 OK 44.04ยตs 194
2024-01-30T18:52:36.685185Z INFO request{id=34008}: radicle_httpd: 127.0.0.1:52700 "GET /api/v1/node HTTP/1.1" 200 OK 622.388ยตs 492
```
When authenticated, the web client is basically an interface to your local node. For example, assuming you cloned the `heartwood` repository, the URL would be: https://app.radicle.xyz/nodes/127.0.0.1:8080/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Here `127.0.0.1:8080` is the local address of your node. You can replace this with `seed.radicle.garden` to browse the repositories on our public seed node, e.g. `https://app.radicle.xyz/nodes/seed.radicle.garden`, which is currently replicating all newly initialized repositories.
You can always disconnect from the web interface by entering `Ctrl-C` in the terminal where `rad web` is running, or by accessing the `Disconnect` command via your alias in the top right of the interface.
If you find any bugs, we encourage you to create an issue in our `radicle-interface` repo.
$ rad clone rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5
$ cd radicle-interface
$ rad issue open --title "<title>" --description "<description>"
---
This marks the end of our initial foray into Radicle. As we move forward to [Chapter 2](#), we'll dissect the collaborative mechanisms at play, exploring issues and patches from the unique perspectives of both contributors and delegates. It's here that the true kernal of *code collaboration* begins to unfold, so don't hesitate to jump into the depths of what our protocol has to offer you!
# Chapter 2: Collaborating the Radicle Way
Now is the time to delve into Radicle's approach to storing and working with social artifacts like issues and patches. We leverage Git's distributed version control system, to both allow you to maintain local copies of your repositories in addition to their associated issues and patches.
You must be familiar with git's commit hash: when you `commit` code changes, a unique hash is generated to identify them. Well in Radicle, issues, patches & their comments work similar to commits since they are all self-contained within a Git repository and hence like commits, are Git objects, referenced by their Git Object ID (OID). These objects are also cryptographically signed by their author which allows collaborative interactions to be independently verified for authenticity by all users, enabling projects to operate independently of centralized platforms.
---
<small>
`๐Learn more:`
The Git OID is a SHA-1 hash, which is a 40-character string that uniquely identifies objects within a Git repository. This identification is part of Git's content-addressable storage system, ensuring the integrity of every data piece.
</small>
---
You know what this all means? One day, you'll be able to create an AI agent that codes and thinks like you a lot easier than if you dumped your brain on a megacorp owned platform. There, it is dirty. Issues and thoughts are not hashed nor associated with public keys. The platform sort of owns all your data and is freely creating AI models from it all, without giving you back anything.
That's the old web. The beauty of Radicle is that everything is hashed. Whenever it is you are ready to create your AI agent, all your data is accessible from your local machine. No API calls or special bots are required to extract the data from some central server. That's not to say we have this AI plugin developed... but if you want to take a crack at it, [let us know](#).
## Working with issues
*The more we git together
Together, together
The more we git together
The happier we'll be*
We'll kick off from my perspective, as I open an issue in a repository where I'm a contributor, but not a delegate. But before I open this issue we should first get to know our trusted friend, the COB. Collaborating on issues and patches is not natively supported by Git, so we had to extend it. We named this data type a "Collaborative Object" or COB and it uses Conflict-Free Replicated Data Types (CRDTs) for data consistency. COBs are one of the necessary ingredients of the Radicle Special Sauce.
---
<small>
`๐Learn more:`
Git has the command `git format-patch` which formats changes into a patch file that can be shared with others for discussion over email. While that is the preferred workflow for Linux kernal development, it is not the standard workflow of *pull requests* that people have grown more accustomed to.
A Conflict-Free Replicated Data Type (CRDT) is a data structure that allows distributed systems to update data independently and resolve inconsistencies without central coordination. CRDTs ensure that all copies converge to the same state, making them ideal for environments with intermittent connectivity or where immediate consistency is not required.
</small>
---
<small>
`๐พ Radlien Tip:`
Radicle currently includes three predefined COBs to support code collaboration: `issue`, `patch`, and `id`. These are associated with unique namespaces, in reverse domain name notation, such as `xyz.radicle.issue` or `xyz.radicle.patch`, to allow for extensibility. For example, issues are stored under `refs/cobs/xyz.radicle.issue/<ISSUE-ID>`, but it's also possible to define a custom issue COB under the namespace `org.YourOrg.issue` or an entirely new COB such as `org.YourOrg.YourCOB`. This means that Radicle can be extended with new collaborative data types without changing the protocol version.
</small>
---
Now, let's open an issue and see how this works.
I'm going to `cd` into my directory for the `dark-star-data` project that I'm collaborating on, and create an issue with `rad issue open` by also passing in a title and description with the command.
```
$ cd dark-star-data
$ rad issue open --title "Establish data standards for IUI Dark Star Data group" --description "As we go out and recruit the Neboriens and other intelligences to join the Intergalactic Union of Intelligences (IUI), we are going to have to establish standards for Dark Star data submissions."
```
Next, you'll see the issue that you just opened.
```
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Title Establish data standards for IUI Dark Star Data group โ
โ Issue e4255cc2a0a65b543c2b5badac14bf9e0d9f409f โ
โ Author paxel (you) โ
โ Status open โ
โ โ
โ As we go out and recruit the Neboriens and other โ
โ intelligences to join the Intergalactic Union of โ
โ Intelligences (IUI), we are going to have to establish โ
โ standards for Dark Star data submissions. โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โ Synced with 1 node(s)
```
You can always see a table with all of the issues associated to the repository by running `rad issue` within its directory.
```
$ rad issue
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ โ ID Title Author โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ 3e2f653 Add anomalous data from ship 897AF calyx (โฆ โ
โ โ badda04 Recruit Neboriens to join IUI and share dark star data calyx (โฆ โ
โ โ e4255cc Establish data standards for IUI Dark Star Data group paxel zโฆ โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
```
You may have to widen your terminal window to see all of the available columns. You can add a comment to an issue with `rad issue comment <issue-id> --message "<message>"` and view an issue and read all its comments with `rad issue show <issue-id>`.
Note that you don't have to use the full issue identifier. An unambiguous prefix, like the one listed in the `rad issue` ID column also works.
```
$ rad issue comment 3e2f65 --message "I can help"
โญโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ paxel (you) now 74faf0e โ
โ I can help. โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
$ rad issue show 3e2f65
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Title Add anomalous data from ship 897AF โ
โ Issue 3e2f653383f0d2fe21ef4e859a25925c364c740a โ
โ Author calyx (you) โ
โ Status open โ
โ โ
โ Before we onboard new IUI members like the Neborians, it is โ
โ important we upload the data from ship 897AF. I just โ
โ reviewed the database and it seems this is missing. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ paxel z6MkvZwโฆ7aCGq3C 6 hours ago 74faf0e โ
โ I can help. โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
```
## Assigning issues
Now, utilizing my *remote viewing* superpowers, we'll embark on a mental journey to Calyx's workstation who, as a delegate of `dark-star-data`, will assign an issue from a maintainer's standpoint.
---
<small>
`๐Learn more:`
Remote viewing (RV) is an alleged paranormal ability that involves gaining information about a distant or unseen object, event, person, or location with the mindโs eye. Remote viewers vividly describe these hidden details, relying solely on the power of their mental faculties.
</small>
---
As a maintainer, Calyx is reviewing an issue he opened.
```
$ rad issue show 3e2f65
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Title Add anomalous data from ship 897AF โ
โ Issue 3e2f653383f0d2fe21ef4e859a25925c364c740a โ
โ Author calyx (you) โ
โ Status open โ
โ โ
โ Before we onboard new IUI members like the Neborians, it is โ
โ important we upload the data from ship 897AF. I just โ
โ reviewed the database and it seems this is missing. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ paxel z6MkvZwโฆ7aCGq3C 6 hours ago 74faf0e โ
โ I can help. โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
```
He sees that Paxel wants to help with the issue, and decides to assign it to him, and sends a comment.
```
$ rad issue assign 3e2f653 --add did:key:z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C
$ rad issue comment 3e2f653 --message "Great, I've assigned it to you"
```
Now we can view the issue again with `rad issue show <issue-id>` to see the assignee & comment:
```
$ rad issue show 3e2f65
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Title Add anomalous data from ship 897AF โ
โ Issue 3e2f653383f0d2fe21ef4e859a25925c364c740a โ
โ Author calyx (you) โ
โ Assignees z6MkvZwโฆ7aCGq3C โ
โ Status open โ
โ โ
โ Before we onboard new IUI members like the Neborians, it is โ
โ important we upload the data from ship 897AF. I just โ
โ reviewed the database and it seems this is missing. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ paxel z6MkvZwโฆ7aCGq3C 6 hours ago 39134b6 โ
โ I can help. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ calyx (you) 2 minutes ago 922fac7 โ
โ Great, I've assigned it to you. โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
```
---
<small>
`๐พ Radlien Tip:`
There's a lot more you can do with issues, such as:
* Deleting with `rad issue delete <issue-id>`
* Editing with `rad issue edit <issue-id>`
* Labeling with `rad issue label <issue-id> --add <label>`
We don't want to overwhelm you though! Check out `rad issue --help` for more details.
</small>
---
## Creating a patch, as if by magic
Zooming back to my machine, we see that Calyx has assigned the issue to us. To address it, we'll start by making changes on a new feature branch of our working copy, and then create a patch.
For example, I'll navigate to the working copy of the repository via `cd`. Then I'll create and checkout a new branch, create a new file that addresses the issue, and add and commit the changes:
$ cd dark-star-data
$ git checkout -b add/anomalous-data-2219281
$ ... add new file ...
$ git add anomalous-data-2219281.csv
$ git commit -m 'add anomalous data from 2219281'
<!-- [add/anomalous-data-2219281 b766431] add anomalous data from 2219281
1 file changed, 4 insertions(+)
create mode 100644 anomalous-data-2219281.csv-->
Once our changes are ready to be proposed as a patch, we push them with the command:
$ git push rad HEAD:refs/patches
Here we use `HEAD` to represent our currently checked-out branch's latest commit, but we could also use the branch name or even an arbitrary commit hash. Radicle will then open your editor, where you can edit the patch title and enter a description. Once you're done, simply save and exit your editor. The patch should then be opened, with its identifier printed out.
```
$ git push rad HEAD:refs/patches
โ Patch e5f0a5a5adaa33c3b931235967e4930ece9bb617 opened
hint: to update, run `git push` or `git push rad -f HEAD:patches/e5f0a5a5adaa33c3b931235967e4930ece9bb617`
โ Synced with 1 node(s)
https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z3cyotNHuasWowQ2h4yF9c3tFFdvc/patches/e5f0a5a5adaa33c3b931235967e4930ece9bb617
To rad://z3cyotNHuasWowQ2h4yF9c3tFFdvc/z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C
* [new reference] HEAD -> refs/patches
```
When you push changes to a cloned repository for the first time using Radicle, a local fork of the repository becomes associated to your Node ID. If this push includes a patch, the use of `refs/patches` acts as a "magic ref." While this looks like a special Git branch name, it's more of a command that is processed by Radicle's remote helper to execute specific actions. It is termed a "magic ref" due to its ability to extend standard Git functionality, integrating Radicle's flavor of patch management directly into the Git workflow. Rather than pushing directly to this ref, the operation involves:
1. Opening the patch by generating a unique Git Object ID (OID) for it and storing it along with your other collaborative objects (COBs) in Radicle's storage system.
2. It creates a remote tracking branch and sets your branch upstream to a path like `rad/patches/<OID>`, or like in our example above, `rad/patches/e5f0a5a5adaa33c3b931235967e4930ece9bb617`.
---
<small>
`๐Learn more:`
Magic refs were inspired by Gerrit, a code collaboration tool developed by Google, which initially introduced this concept.
</small>
---
Consequently, any subsequent pushes from your original branch will update the patch, maintaining synchronization between your local changes and the remote branch that is published to the network.
Let's take a look at our remote tracking branches with the common command `git branch -r` to understand this better.
```
$ git branch -r
calyx@z6Mkgom1bTxdh9fMFxFNXFMw3SbXnma6NARdsfcFuunurCap/main
rad/main
rad/patches/e5f0a5a5adaa33c3b931235967e4930ece9bb617
```
Here we see the repository delegate's default branch (starting with `calyx`), the other is my default branch `rad/main`, and we also see the branch for the patch I just opened, starting with `rad/patches`.
We can also confirm that the patch branch is in storage:
```
$ git ls-remote
From rad://z3cyotNHuasWowQ2h4yF9c3tFFdvc
e81db74197f48cc5198d9c03cceaec955af82abf refs/heads/main
80b8d420658834afc444a13c03f0c3ff6875a71c refs/heads/patches/e5f0a5a5adaa33c3b931235967e4930ece9bb617
```
## Sometimes you update patches
Sometimes you submit a patch prematurely. Sometimes you update patches.
To update a patch, we simply make our changes locally, commit the changes via `git commit --amend` and push via `git push --force`. As with opening a patch, you will be asked to enter a reason for updating the patch, via your editor. Simply save and exit when you're done; or leave it blank to skip entering a reason.
$ open anomalous-data-2219281.csv
$ ... make changes ...
$ git commit --amend
$ git push --force
<!-- [add/anomalous-data-2219281 80b8d42] add anomalous data from 2219281
Date: Sun Feb 4 11:34:09 2024 -0800
1 file changed, 4 insertions(+)
create mode 100644 anomalous-data-2219281.csv-->
Note that this will only work if the current branch upstream is set correctly. This upstream is set automatically when a patch is opened from a branch, as we just recently discussed.
$ git push --force
โ Patch e5f0a5a updated to revision 4d0c1156f8ac7af2297d1314cd7556185cd16ae4
โ Synced with 1 node(s)
https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z3cyotNHuasWowQ2h4yF9c3tFFdvc/patches/e5f0a5a5adaa33c3b931235967e4930ece9bb617
To rad://z3cyotNHuasWowQ2h4yF9c3tFFdvc/z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C
+ b766431...80b8d42 add/anomalous-data-2219281 -> patches/e5f0a5a5adaa33c3b931235967e4930ece9bb617 (forced update)
In this current example, we used the `--force` option, since the commit was amended. This is common practice when a patch has been reworked after receiving a review.
---
<small>
`๐พ Radlien Tip:`
If the branch upstream is not set to the patch reference, ie. *rad/patches/<patch-id>*, you can do so using `rad patch set <patch-id>`.
</small>
---
You can always display the patch metadata and comments using `rad patch show <patch-id>`. Similar to issues, you don't have to use the full patch identifier.
```
$ rad patch show e5f0a5a5adaa3
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Title add anomalous data from 2219281 โ
โ Patch e5f0a5a5adaa33c3b931235967e4930ece9bb617 โ
โ Author paxel (you) โ
โ Head 80b8d420658834afc444a13c03f0c3ff6875a71c โ
โ Branches add/anomalous-data-2219281 โ
โ Commits ahead 1, behind 0 โ
โ Status open โ
โ โ
โ this is the data from ship 897AF. i want to contribute it to the โ
โ dataset. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 80b8d42 add anomalous data from 2219281 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ opened by paxel (you) (b766431) 58 minutes ago โ
โ โ updated to 4d0c1156f8ac7af2297d1314cd7556185cd16ae4 (80b8d42) 44 minutes ago โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
```
## Merging patches into the canonical
We journey again into Calyx's workstation to collaborate on patches from a maintainer's perspective. They will check it out, review it, make changes, and then merge it.
First, within the repository, Calyx runs `rad patch` and notices there is a new patch.
```
$ rad patch
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ โ ID Title Author Head + - Updated โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ e5f0a5a add anomalous data from 2219281 z6MkvZwโฆ7aCGq3C 80b8d42 +4 -0 1 hour ago โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
```
Calyx then runs `rad patch checkout <patch-id>`
```
$ rad patch checkout e5f0a5a
โ Switched to branch patch/e5f0a5a
โ Branch patch/e5f0a5a setup to track rad/patches/e5f0a5a5adaa33c3b931235967e4930ece9bb617
```
When working with patches opened by peers, itโs often useful to be able to checkout the code in its own branch. With a patch checkout, you can browse the code, run tests and even propose your own update to the patch.
What `rad patch checkout` does is create and switch to a new local branch on Calyx's device, `patch/e5f0a5a`, which is synchronized with the patch head -- also known as the patch's remote tracking branch initially created by Paxel, `rad/patches/e5f0a5a5adaa33c3b931235967e4930ece9bb617`.
It's a rare occasion that you someone submits patch and they didn't miss something. There's likely always a nit. Sometimes it's important you just take control and make the change yourself, for efficiency.
---
<small>
`๐Learn more:`
In code reviews, the term "nit" refers to *nitpicking*: the identification of minor issues that, while not significantly impacting the functionality of the code, are still incorrect. Examples include typos in comments, unnecessary semicolons, or superfluous empty lines.
</small>
---
Upon reviewing the patch, Calyx notices a mistake in the column name in the associated data file. He updates the file, commits changes, and then pushes them with `git push rad -o patch.message="<message>"`. The latter `patch.message` option allows Calyx directly provide a comment related his revision while bypassing the editor.
```
$ open anomalous-data-2219281.csv
$ ... make changes ...
$ git add .
$ git commit -m "Updated column name to Zone from Location"
$ git push rad -o patch.message="Fix location column so it is called Zone"
```
Updating it this way will tell others about the corrections we needed before merging the changes.
```
$ git push rad -o patch.message="Fix location column so it is called Zone"
โ Patch e5f0a5a updated to revision 1e0596d917725c447106b1efc900bebf4b95a810
โ Synced with 1 node(s)
https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z3cyotNHuasWowQ2h4yF9c3tFFdvc/patches/e5f0a5a5adaa33c3b931235967e4930ece9bb617
To rad://z3cyotNHuasWowQ2h4yF9c3tFFdvc/z6Mkgom1bTxdh9fMFxFNXFMw3SbXnma6NARdsfcFuunurCap
* [new branch] patch/e5f0a5a -> patches/e5f0a5a5adaa33c3b931235967e4930ece9bb617
```
Now, he does `rad patch show <patch-id>` to check out the state of the patch:
```
$ rad patch show e5f0a5a
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Title add anomalous data from 2219281 โ
โ Patch e5f0a5a5adaa33c3b931235967e4930ece9bb617 โ
โ Author z6MkvZwโฆ7aCGq3C โ
โ Head 80b8d420658834afc444a13c03f0c3ff6875a71c โ
โ Commits ahead 1, behind 0 โ
โ Status open โ
โ โ
โ this is the data from my spacecraft. i want to contribute it to the โ
โ dataset. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 80b8d42 add anomalous data from 2219281 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ opened by z6MkvZwโฆ7aCGq3C (b766431) 2 hours ago โ
โ โ updated to 4d0c1156f8ac7af2297d1314cd7556185cd16ae4 (80b8d42) 2 hours ago โ
โ * revised by calyx (you) in 1e0596d (25f8515) 3 minutes ago โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
```
Here we see that Calyx's changes are associated to the commit hash `25f8515`, and the revision identifier `1e0596d`. He is going to accept this revision, via `rad patch review <patch-id> --revision <revision-id> --accept`.
```
$ rad patch review e5f0a5a --revision 1e0596d --accept
โ Patch e5f0a5a accepted
โ Synced with 1 node(s)
```
There are a few more steps to get this patch merged into the repository's default branch `main`. Calyx needs to `git checkout main`, then `git merge patch/e5f0a5a` which merges the revised patch branch into his local main branch, and then finally `git push rad main` to publish his changes to the network. Since Calyx is the only delegate on this repository, this results in the canonical repository version (or head reference) being updated.
```
$ git checkout main
Switched to branch 'main'
Your branch is up to date with 'rad/main'.
$ git merge patch/e5f0a5a
Updating e81db74..25f8515
Fast-forward
anomalous-data-2219281.csv | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 anomalous-data-2219281.csv
$ git push rad main
โ Patch e5f0a5a5adaa33c3b931235967e4930ece9bb617 merged at revision 1e0596d
โ Canonical head updated to 25f851529d68180a780cfafc15a48b89208ba8c4
โ Synced with 1 node(s)
https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z3cyotNHuasWowQ2h4yF9c3tFFdvc/tree/25f851529d68180a780cfafc15a48b89208ba8c4
To rad://z3cyotNHuasWowQ2h4yF9c3tFFdvc/z6Mkgom1bTxdh9fMFxFNXFMw3SbXnma6NARdsfcFuunurCap
e81db74..25f8515 main -> main
```
Once published to the network, the patch is automatically closed. This happens when the commit hash of the default branch matches the commit hash of the patch.
```
$ rad patch
Nothing to show.
```
---
<small>
`๐พ Radlien Tip:`
Patch commands work similar to issues. You can:
* Delete with `rad patch delete <patch-id>`
* Edit with `rad patch edit <patch-id>`
* Label with `rad patch label <patch-id> --add <label>`
For more advanced details on how to work with patches, read the manual: `rad patch --help`
</small>
---
## From remote viewing to adding remotes
Whenever you `init` or `clone` a repository, you follow all peers by default which means that everyone's patches will always be displayed as remotes.
But if a peer becomes a regular project collaborator, it would be important for maintainers to add the peer itself as a Radicle remote to track their changes and directly checkout their branches that haven't been submitted as patches yet.
So while we have been metaphorically remote viewing Calyx's operations, Calyx can also technically *remote view* any of our feature branch working copies that we have pushed to the network, first by adding us as a remote with `rad remote add <nodeID> --name <alias> --sync --fetch`.
$ rad remote add z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C --name paxel --sync --fetch
This allows Calyx to follow us and keep up with our changes, and creates a remote tracking branch in their working copy.
```
$ git remote -v
paxel rad://z3cyotNHuasWowQ2h4yF9c3tFFdvc/z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C (fetch)
paxel rad://z3cyotNHuasWowQ2h4yF9c3tFFdvc/z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C (push)
rad rad://z3cyotNHuasWowQ2h4yF9c3tFFdvc (fetch)
rad rad://z3cyotNHuasWowQ2h4yF9c3tFFdvc/z6Mkgom1bTxdh9fMFxFNXFMw3SbXnma6NARdsfcFuunurCap (push)
```
In the above output, we see the names of the remotes in the left. To switch to the remote that Calyx just added, they can use `rad remote --name paxel`.
```
$ rad remote --name paxel
paxel z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C (fetch)
rad (canonical upstream) (fetch)
rad z6Mkgom1bTxdh9fMFxFNXFMw3SbXnma6NARdsfcFuunurCap (push)
```
Next they can fetch our latest changes with `git fetch paxel`, seeing that we created a new branch, `feature-branch`.
```
$ git fetch paxel
From rad://z3cyotNHuasWowQ2h4yF9c3tFFdvc/z6MkvZwzK64f3GuDcAs6dEcje89ddfHkBjS1v9Dkh7aCGq3C
* [new branch] feature-branch -> paxel/feature-branch
```
They can now see our list of branches when running `git branch -a`. If they were so inclined and wanted to peek around, Calyx could checkout our branch via `git checkout remotes/paxel/feature-branch`.
```
$ git branch -a
add/anomalous-data-2219281
* main
patch/e5f0a5a
remotes/paxel/main
remotes/paxel/feature-branch
remotes/paxel/patches/e5f0a5a5adaa33c3b931235967e4930ece9bb617
remotes/rad/main
```
Now I'm basically just reteaching you git in the last few steps, but the point is to show you basically how Radicle uses remotes to provide you the capability of peering into each peer, leveraging paranormal powers -- I mean, novel git peer-to-peer networking magic.
## Synchronizing the canonical
Okay so our journey into remote viewing Calyx has ended, and we are now back at my workstation. Now that the patch has been merged into the default `main` branch by Calyx, I can synchronize my `main` branch to the canonical, which includes my patch now.
First, we confirm that our `main` is behind:
```
$ git rev-parse main
e81db74197f48cc5198d9c03cceaec955af82abf
```
In the last step, we saw that the canonical head was updated to `25f851529d68180a780cfafc15a48b89208ba8c4`, hence this is indeed behind.
Next, we call `rad sync --fetch` to fetch the latest changes from the network:
```
$ rad sync --fetch
โ Fetching rad:z3cyotNHuasWowQ2h4yF9c3tFFdvc from z6MkrLMโฆocNYPm7..
โ Fetching rad:z3cyotNHuasWowQ2h4yF9c3tFFdvc from z6Mkg5Zโฆ4Q8qCHw..
โ Fetched repository from 2 seed(s)
```
Now let's `git checkout main` and pull the maintainer's changes via `git pull --all --ff`.
```
$ git checkout main
Switched to branch 'main'
Your branch is up to date with 'rad/main'.
$ git pull --all --ff
Fetching rad
From rad://z3cyotNHuasWowQ2h4yF9c3tFFdvc
e81db74..25f8515 main -> rad/main
Fetching calyx@z6Mkgom1bTxdh9fMFxFNXFMw3SbXnma6NARdsfcFuunurCap
From rad://z3cyotNHuasWowQ2h4yF9c3tFFdvc/z6Mkgom1bTxdh9fMFxFNXFMw3SbXnma6NARdsfcFuunurCap
e81db74..25f8515 main -> calyx@z6Mkgom1bTxdh9fMFxFNXFMw3SbXnma6NARdsfcFuunurCap/main
Updating e81db74..25f8515
Fast-forward
anomalous-data-2219281.csv | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 anomalous-data-2219281.csv
```
Now we can verify our main branch is up to date with the maintainer's main:
```
$ git rev-parse main
25f851529d68180a780cfafc15a48b89208ba8c4
```
## Collaborating the web interface way
You may be curious -- can you work with issues and patches with a web interface? The answer is: Yes!
If you missed it, first check out [the web interfaces section of Chapter 1](#But-what-about-web-interfaces). Basically, make sure your node is running, and then open the interface by running `rad web`:
$ rad web
This will open the web client at `app.radicle.xyz` and if properly authenticated, you'll see a list of your repositories. You can click on one, and then navigate to its issues and patches. New issues can be both created, commented on, and updated with the web interface. Patches cannot be created from the interface, but their name & description can be edited, and you can add comments.
---
And, that's a wrap! You now know the basics of how to leverage Radicle for code collaboration. Note that we don't have code review features yet for patches, but that will be coming in a future release -- it's on our immediate roadmap. If you still feel you're in need of additional guidance, join us in our [chatroom on Zulip][zulipchat] and ask your questions in the support channel. Consider continuing on to [Chapter 3](#Chapter-3) to learn more about advanced commands when it comes to setting rules and configurations for how your node seeds repositories.
[zulipchat]: https://radicle.zulipchat.com/
# Chapter 3: Seeding
Radicle stands as a sovereign convergence point for those eager to host and synchronize not just their own Git repositories, but also to become *seeds* for the repositories of others. Inspired by BitTorrent, we have adopted the terminology *seeding* to describe the synergetic act of hosting, distributing, and synchronizing a repository across the network.
Seeding in this context transcends mere synchronization; it embodies the act of contributing to the network's vitality by providing essential resources like bandwidth, storage, and data availability. This network effort ensures that every Git repository, whether one's own or that of a fellow developer, remains accessible and in perpetual sync, fostering a collaborative ecosystem where data sovereignty flourishes.
Your Radicle node isn't just seeding random repositories, you have an active choice in deciding the data that is hosted on your device. Each time you use the `rad clone` or `rad seed` or `rad init` commands, your node's *seeding policy* is updated, specifying new repositories to seed.
In this chapter, you are going to learn more about the ins and outs of seeding and the different commands that make changes to your node's seeding policy. We will start from the beginning, refreshing your memory on the points we went through in [Chapter 1](#) when we first covered seeding, while providing a more comprehensive overview.
This particular guide is oriented toward the more prominent Radicle user we are expecting, where the node is installed on a personal computer or laptop. If you're interested in learning more about how to set up an always-on seed node, that is either a public seed node or set up as sovereign infrastructure for your community, check out the [Seeder's Guide](https://radicle-docs-nine.vercel.app/guides/seeder) instead.
## Default seeding policy
First it is important to understand your node's configuration file which defines your default seeding policy.
When you set up your Radicle Node using `rad auth`, a configuration file is created that is populated with defaults. You can view this file by running `rad config` in your terminal.
$ rad config
At the very bottom of this file, you will see:
...
"policy": "block",
"scope": "followed"
...
The possible options for *policy* are `allow` or `block`, while for *scope* the options are `all` or `followed`. When your node's policy is `block` with a scope of `followed`, it means that your node is *selectively seeding* repositories based on modifications you're actively making to your node, which is the norm for user nodes.
You can also view your node's *default policy* alone with `rad config get node.policy`:
$ rad config get node.policy
To override the default policy for a specific repository, we can decide to *allow* a repository to be seeded by calling commands like `rad clone`, `rad seed`, or `rad init`. This results in your node becoming a seed of the related repository, which is passed with an alternate policy and scope of "allow" and "all", respectively. This means that your node will subscribe to updates from *all peers* for repositories you're interested in.
For example, let's try this out by seeding the Heartwood repository.
$ rad seed rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
This will override the default `block` rule for this one specific repository.
If you later change your mind, and you no longer want to seed Heartwood, `--delete` can be passed:
rad seed --delete rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Now without a seeding policy for this repository, the default policy of `block` will apply again.
To view the policy of a specific repository, use the `rad inspect` command. For example:
rad inspect rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 --policy
Note that this will fallback to the default policy if you haven't set any repository specific policy.
Finally, to view all seeding policies that have been set on repositories, simply enter `rad seed` with no options. This will list all configured policies.
<!-- do rad ls, and rad ls --all - work through heartwood seeding example-->
In the case of a node with an *open* seeding policy, where the default is `allow`, and all repositories are being seeded by default, we can explicitly *block* certain repositories from being seeded. For example,
rad block rad:z9DV738hJpCa6aQXqvQC4SjaZvsi
This will override the default policy and ensure that this repository is never replicated on your node.
---
<small>
`๐พ Radlien Tip:`
It is not recommended that you change your node's default policy to `allow` unless you want to seed all of the repositories submitted to the network. If that intrigues you, check out the [Seeder's Guide](#) for instructions, as there are other considerations to take into account.
</small>
---
## Followed
When you run `rad seed` or `rad clone` without specifying a scope, your node will subscribe to updates from *all of the repositories peers*. This default behavior can be changed by passing `--scope followed` with the `rad seed` or `rad clone` commands, to only subscribe to updates from the repository delegates plus any node that is explicitly followed.
$ rad seed rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 --scope followed
If `--scope followed` was not originally provided when seeding or cloning the repository, or you want to make updates to one of the repositories you've initialized, you can always update the repository's policy at any point in the future by running the `rad seed` command with this option.
But this command wouldn't do much without you actively managing your *follow policy* which specifies the nodes you are following. How do you update this policy to specify nodes to follow? It's as simple as `rad follow <nid>`.
$ rad follow z6Mkgom1bTxdh9fMFxFNXFMw3SbXnma6NARdsfcFuunurCap
If you change your mind, you can always remove a node with `rad unfollow <nid>`.
$ rad unfollow z6Mkgom1bTxdh9fMFxFNXFMw3SbXnma6NARdsfcFuunurCap