Introduction

Welcome to the Radicle docs! Whether you’re coming across Radicle for the first time or looking to dig into how the Radicle stack works from a technical perspective, you’re in the right place.

For a technical overview of Radicle, including some of the architectural choices we’ve made, a good place to start is the Radicle P2P architecture section below.

If you want to dive straight in and play around with Radicle for yourself, follow the installation instructions and then the Radicle Tutorial in the docs below.




  ;;;;;        ;;;;;        ;;;;;  
  ;;;;;        ;;;;;        ;;;;;  
  ;;;;;        ;;;;;        ;;;;;  
  ;;;;;        ;;;;;        ;;;;;  
..;;;;;..    ..;;;;;..    ..;;;;;..
 ':::::'      ':::::'      ':::::' 
   ':`          ':`          ':`   


What is Radicle?

Radicle is a new stack for code collaboration, that includes a few simple utilities we've created for this initial release to demonstrate the core functionality. Think of Radicle as a Github or Gitlab alternative (albeit an exceedingly simple one right now). You can also combine Radicle with these services if you're not ready to switch over entirely.

Instead of being hosted by Github's servers, or hosted on servers that you yourself manage and deploy, issues, patches (i.e. pull-requests/merge-requests) and optionally repos are distributed via IPFS. To use it, you don't need to rely on centralized services, nor go through the trouble of self-hosting.

When you initialize or check out a Radicle project, Radicle stores the project id in the repository's git config. When you run commands like rad issue or rad patch from inside that repo, Radicle reads that project id, and asks the Radicle daemon to either fetch the right data from IPFS (when reading), or submit it to the project owners (when writing). This allows you to deal with all the tasks associated with a project right from your repo directory.

To collaborate on a project, all you need to do is share your project id.

The main commands:

  • rad project init : Creates a new project
  • rad project checkout : Checkout (clone) someone else's project
  • rad issue list : List the issues in a project
  • rad issue new : Create a new issue in a project
  • rad issue comment : Comment on an issue
  • rad patch propose : Propose that a commit be merged into a project
  • rad patch accept : Merge a patch

Radicle was designed to make it easy to create new utilities, or modify existing ones. If you want to require that bug reports have "How to reproduce" sections, or if you want patches touching certain directories to be deemed invalid and immediately rejected, or if you want to allow only certain people to open issues, you can do all that. However, this involves programming in the Radicle language, for which documentation is still lacking.

Installation & Setup

Disclaimer: Radicle is alpha technology and in heavy development. All your data may be lost. We do not guarantee backwards compatibility between releases. It’s important to remember that this is experimental software and should be treated as such.

This release is aimed for developers and early-adopters who want to get a glimpse into what we are building and help shape the product through feedback or contributions to the Radicle project.

OS X

brew tap radicle-dev/radicle
brew install radicle-alpha

To run the rad commands, you must have both a Radicle daemon, and Radicle IPFS daemon running. You can have them always run in the background using brew services with the following commands:

brew services start radicle-alpha-ipfs
brew services start radicle-alpha

Or if you prefer running them manually every time, check the section below.

Finally, interacting with the Radicle utilities requires that you have a set of Radicle keys. You can initialize your keys with the rad key create command.

Debian/Ubuntu

For Debian-based systems we provide packages.

wget https://storage.googleapis.com/static.radicle.xyz/releases/radicle_latest_amd64.deb
sudo apt install ./radicle_latest_amd64.deb

To run the rad commands, you must have both a Radicle daemon, and Radicle IPFS daemon running. The package includes systemd service files to always have the daemons running in the background. To start the daemons run:

systemctl --user start radicle-daemon

You can check the status of a service with systemctl --user status <service>.

Or if you prefer running them manually every time, check the section below.

Finally, interacting with the Radicle utilities requires that you have a set of Radicle keys. You can initialize your keys with the rad key create command.

Install From Source

Radicle requires ipfs and git-remote-ipfs to run properly. When installing Radicle from source, make sure you have both of these installed first.

To build Radicle from source you need to install stack.

git clone https://github.com/radicle-dev/radicle.git
cd radicle

stack install

Note that stack might take as much as 4GB of memory to build Radicle.

Manually running background processes

Radicle requires 2 background processes to be running: radicle-daemon and radicle-ipfs-daemon.

If you have installed Radicle via the brew / debian packages, the necessary background processes should be already available as systemd or brew services respectively (see above).

To run these manually, you can use the following rad commands:

rad daemon-ipfs
rad daemon-radicle

Finally, interacting with the Radicle utilities requires that you have a set of Radicle keys. You can initialize your keys with the rad key create command.

Tutorial 1: Contributor

Make sure you in install Radicle if you haven't already, and then you're set to try the Radicle tutorial.

In the Radicle tutorial you'll learn to use some of Radicle's basic collaboration tools. In the first half of the tutorial you'll contribute changes to a Radicle project maintained by someone else, where you'll learn the three main Radicle commands: rad project, rad issue, and rad patch.

Then, in part 2, you'll see the other side of the collaboration by walking through the maintainer workflow.



                  _(_)_                          wWWWw   _        
      @@@@       (_)@(_)   vVVVv     _     @@@@  (___) _(_)_      
     @@()@@ wWWWw  (_)\    (___)   _(_)_  @@()@@   Y  (_)@(_)     
      @@@@  (___)     `|/    Y    (_)@(_)  @@@@   \|/   (_)\      
       /      Y       \|    \|/    /(_)    \|      |/      |      
    \ |     \ |/       | / \ | /  \|/       |/    \|      \|/     
jgs \\|//   \\|///  \\\|//\\\|/// \|///  \\\|//  \\|//  \\\|//    
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


Welcome to the Radicle Garden, a new-found island located somewhere off the ASCII shores of tilde.town. Today we're going to learn how to use the Radicle collaboration utilities by adding a plot of our own to the Radicle Garden map.

Contribute to the Radicle Garden

The Radicle Garden is a project created using Radicle, with a version hosted on the web at www.radicle.xyz/garden. A Radicle project contains a git repository as well as the all the issues and proposals associated with that repo.

Before we start contributing, we'll need to download a copy to our computer by checking out the project. To do that we need the project-id: 12D3KooWRsrUcqCFU3ompktgTo197gguibN3cjmgaoQy8AS54iHn, and then we'll run:

$ rad project checkout 12D3KooWRsrUcqCFU3ompktgTo197gguibN3cjmgaoQy8AS54iHn
radicle-garden
Initialized empty Git repository in /home/gardener/projects/radicle-garden/.git/
Warning: Permanently added the RSA host key for IP address '192.30.253.112' to the list of known hosts.
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 8 (delta 1), reused 4 (delta 1), pack-reused 0
Unpacking objects: 100% (8/8), done.
From github.com:radicle-dev/garden
 * [new branch]      master     -> origin/master

In the output shown above we can see that rad project uses git behind the scenes to clone the project from a remote repo hosted on IPFS into a new folder named after the project-id.

Let's learn a little more about this project by moving into the newly created directory with $ cd radicle-garden and then listing what's in the folder.

$ ls -a
.  ..  .git  2019-03-01_tulip.txt  2019-03-02_mesa.txt

As we can see, the Radicle project folder has a .git directly inside, like any other git repo.

Now let's take a look at what's in these garden text files:

$ cat 2019-03-01_tulip.txt

                ☼

    (%)(%)(%)
    '|''|''|'
    \|/\|/\|/
   [~~~~~~~~~]
____|~~~~~~~|_______
    |_______|

Oh, very pretty.

$ cat 2019-03-02_mesa.txt

             🌞
   ☁
   ____🐓_
---|     |---------
  /       \      🌵

        ~~
   🐍         ~~

What lovely gardens. It looks like each garden file contains an ASCII image. These images are combined to create the community garden page located at www.radicle.xyz/garden.

Like our git repo, Radicle stores our issues and patches locally and distributes them over the IPFS network. To look at a list of issues we'll run $ rad issue list while inside the git repo.

$ rad issue list
state    #   title                         author    updated
open     0   Patch proposal not accepted   jane      2019-03-12T10:18:52Z *

2 issues: 1 open, 1 closed

There's only one issue for this project at the moment [note: the output may differ if additions have been made]. Let's take a closer look with $ rad issue show 0.

$ rad issue show 0
open  0  Patch proposal not accepted  jane  2019-03-04T16:41:47Z

**State:** open
**Labels:** []

I made a proposal to add my garden to the map, but when I run `rad patch list` the state is listed as rejected.

Comments
--------

### alex [2019-03-04T16:43:26Z]

It looks like your garden doesn't have the correct dimensions. All gardens should be 20 characters wide and 8 lines high.

If we wanted to add another comment we could run $ rad issue comment <issue-number> <body>.

Creating an issue works just like adding a git commit message—add text at the top and save the file to create the comment.

Now let's make our own garden. First of let's create a new branch and check it out, $ git checkout -b my-garden. Then we'll create a new text file, $ touch YYYY-MM-DD_username.txt and open the file with our favorite editor.

As mentioned in the issue above, the text should fit in a box of 20 characters wide and 8 lines high. Here is an empty 20 x 8 frame to start us off.


╔══════════════════╗ 
║                  ║
║                  ║
║                  ║
║                  ║
║                  ║
║                  ║
╚══════════════════╝

And few ASCII art collections for inspiration:

Also, feel free to copy some of the existing plots in the garden as a starting point.

Once we've planted a few vegetables and feel happy with our garden, we'll save the file, add the staged file, and commit it to the repo using git.

$ git add .
$ git commit -m "Sowing seeds"
[master (root-commit) 798c5c4] Sowing seeds
 1 files changed, 8 insertions(+)
 create mode 100644 YYYY-MM-DD_username.txt

Now let's propose our patch upstream using the commit hash of this git branch.

$ rad patch propose 798c5c4
Proposing patch #1 to 12D3KooWRsrUcqCFU3ompktgTo197gguibN3cjmgaoQy8AS54iHn

Note: Make sure that your commit is on top of origin/master or the patch will fail!

If we want to see the status of our patch we can do that with:

$ rad patch list
state     #   commit        author   updated
pending   45  Sowing seeds  jane     2019-03-19T23:51:47Z

46 patches: 35 accepted, 1 pending, 6 rejected, 4 retracted

Note 1: The author name comes from the local .gitconfig. Note 2: It may take a minute or so until proposed patches show up in this list.

As long as our garden is the correct dimensions, it shouldn't take long for our proposed patch to be accepted and then we'll be able to see our garden on the map at www.radicle.xyz/garden. Also if we check out the master branch, $ git checkout master, and pull in the latest changes, $ git pull origin master, you should see our garden file show up there as well.

~

And that's the end of part 1. If you feel comfortable with that material you can move on to Part 2 of this tutorial, which explains what the same process looks like as a Maintainer.

Tutorial 2: Maintainer

Part 2 of this tutorial walks through how to setup a project as a Maintainer. We'll use the Radicle Garden project again as an example, however, this time you'll need to find a friend to play the contributor role if want to see the entire workflow in action.

Creating the Radicle Garden & managing contributions

Now that we've shown off our green thumb in part 1, let's see what happens on the other side of the collaboration by walking through how the Radicle Garden project was created and how contributions are managed as a maintainer.

First we need to create a Radicle project. To do that we'll run $ rad project init and choose a project name.

Note that the project is created in our current working directory.

$ mkdir acme && cd acme
$ rad project init
? What's the name of your project (Default: acme)? acme
? Briefly describe your project? This is my description
? What kind of repository would you like to use?
1. New peer-to-peer repository (git-ipfs **EXPERIMENTAL**)
2. Add your own remote (e.g.: github / gitlab / ...)
    (see www.radicle.xyz/docs/#git-integration for more info)

We're going to choose option 1 to create a P2P repo distributed using IPFS. When we do, we'll see the following:

=> Assembled rad-issue machine
=> Assembled rad-patch machine
=> project id: 12D3KooW...
=> adding "origin" remote: ipfs://ipns/12D3KooW...
[master (root-commit) e3f2a9a] Radicle Setup
Resolving IPNS name 12D3KooW...
Pushed 1 objects
Updating IPNS link 12D3KooW... to /ipfs/12D3KooW...
To ipfs://ipns/12D3KooW...
* [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
=> project created!

Now we're setup with everything we need to collaborate: a git repo, issues, and proposals.

If we'd like to invite others to contribute, we'll need to give them our project-id, which we can see with:

$ rad project show-id
=> 12D3KooW...
=> Share this project id for people to collaborate with you on your project.

Let's say a collaborator already proposed a patch using the steps outlined in the first section of this guide. We can see a list of all proposed patches, as well as the status of each patch, with $ rad patch list.

$ rad patch list
state     #   commit               author  updated
pending   2   Plant a few flowers  jane    2019-03-19T23:51:47Z *

3 patches: 1 accepted, 1 pending, 1 rejected

Then we can inspect the patch with:

$ rad patch show <PATCH-NUMBER>
accepted 0 Sewing seeds jane 2019-03-01T16:49:28Z

From b118c572a441a774d4577ccb68f67fcfacc58df2 Mon Sep 17 00:00:00 2001
From: jane doe <jane@botanicals.xyz>
Date: Mon, 4 Mar 2019 17:47:15 +0100
Subject: [PATCH] Plant a few flowers

---
2019-03-01_tulip.txt | 8 ++++++++
...

Maybe we'd like to add a comment to request additional changes:

$ rad patch comment <PATCH-NUMBER> "Nice feature, but here is my comment..."
Added comment to Patch <PATCH-NUMBER>

For local testing we can checkout the patch in a branch:

$ rad patch checkout <PATCH-NUMBER>
Switched to a new branch 'patch/<PATCH-NUMBER>'
Applying: [PATCH] Sewing seeds

And then we can either reject the proposal:

$ rad patch reject <PATCH-NUMBER>
Patch <PATCH-NUMBER> has been rejected

or accept it:

$ rad patch accept <PATCH-NUMBER>
Merging proposal <PATCH-NUMBER> with master

Let's check the proposal status one more time to confirm:

$ rad patch list -s accepted
state     #  commit        author    updated
accepted  2  Sewing seeds  jane      2019-01-25 13:27
...

3 patches: 2 accepted, 1 rejected

That's it!

🌻

Rad CLI Reference

rad issue commands

rad issue - Radicle Issue CLI

   Usage:
        rad issue list [(--filter-by-state | --state | -s) <state>] [--fancy]
        rad issue new
        rad issue [show | close | mark-read | mark-unread] <issue-number>
        rad issue comment <issue-number> <comment>
        rad all-read
        rad issue help

     list         - Lists all issues
                    The list can be filtered by state:
                      open, closed
                    The flags for filtering by state:
                      --filter-by-state, --state, -s
                    Filtering by multiple states is possible via '-s <state1> -s
                    <state2> ...'.
                    If the option '--fancy' is appended, the list is opened via
                    fzf (note that fzf has to be installed).
                    If the option '--unread' is appended, only unread issues
                    are listed.
                    Unread issues are marked with a * after the timestamp.
     new          - Create a new issue in $EDITOR
     show         - Show an issue
     comment      - Add a comment to an issue
     close        - Close an issue
                    This command is restricted to the maintainer of the project.
     mark-read    - Mark issue as read
     mark-unread  - Mark issue as unread
     all-read     - Mark all issues as read
     help         - Print this help and exit

rad patch commands

rad patch - Radicle Patch CLI

   Usage:
        rad patch list [(-s | --state | --filter-by-state) <state>] [--fancy]
        rad patch propose <commit>
        rad patch [show | retract | accept | reject | checkout | mark-read | mark-unread] <patch-number>
        rad patch comment <patch-number> <comment>
        rad patch all-read
        rad patch help

     list         - Lists all patches
                    The list can be filtered by state:
                      pending, retracted, accepted, rejected
                    The flags for filtering by state:
                      -s, --state, --filter-by-state
                    Filtering by multiple states is possible via '-s <state1> -s
                    <state2> ...'.
                    If the option '--fancy' is appended, the list is opened via
                    fzf (note that fzf has to be installed).
                    If the option '--unread' is appended, only unread patches
                    are listed.
                    Unread patches are marked with a * after the timestamp.
     propose      - Create a new patch from a single commit
     show         - Show a patch
     comment      - Add a comment to a patch
     retract      - Retract your own patch
                    This command is restricted to the creator of the patch or the
                    maintainer of the project.
     accept       - Accept a patch
                    Automatically merges to master and pushes to origin. This
                    command is restricted to the maintainer of the project.
     checkout     - Checkout a patch locally
                    Creates a new branch 'patch/<patch-number>' and applies the
                    patch to it.
     reject       - Reject a patch
                    This command is restricted to the maintainer of the project.
     mark-read    - Mark patch as read
     mark-unread  - Mark patch as unread
     all-read     - Mark all patches as read
     help         - Print this help and exit

rad project commands

rad project - Radicle project CLI

   Usage:
        rad-project init
        rad-project show-id
        rad-project checkout <PROJECT-ID>

     init         - Initialize a new project
     show-id      - Show the project id
     checkout     - Checkout a project

rad key commands

rad key - Radicle Key Management CLI

   Usage:
        rad key create [--force]
        rad key help

   Creates a new key pair. If `--force` is appended, an existing key pair
   file will be overwritten.
   Per default, key pairs are stored in `$HOME/.config/radicle/my-keys.rad`
   this can be adjusted by setting `$XDG_CONFIG_HOME`.

   The key pair is used for signing actions in the utils. Note that some actions
   are restricted to certain key pairs so deleting or overwriting your key pair
   can lead to loss of some authorisations.

Radicle P2P Architecture

How replication works

Radicle state machines are replicated using IPFS. The state of a machine is fully determined by its input log, and this is exactly what is stored and replicated on IPFS as a linked list. The empty Radicle machine has the address zdpuAyyGtvC37aeZid2zh7LAGKCbFTn9MzdqoPpbNQm3BCwWT, which is just the CID (content-addressed identifier) of {"radicle": true}; there is no significance to this, it's just a way of choosing a CID to represent the empty list of expressions. Subsequent inputs (which are just sequences of Radicle expressions) are stored as documents containing the expressions and a link to the previous input. One only needs the address of the latest input, the "head", to be able to recover the whole log. The owner of a machine uses an IPNS link to point to the head of the list, and the name of this link is then the name of the machine also.

Writing to an RSM (ipfs-pubsub)

To add expressions to a machine, one creates a document with the expressions to be added and adds a link to the previous head of the linked list of inputs:

{
  "expressions": ["(def x 42)", "(def y (+ x x))"],
  "previous": {
    "/": "zdpuApnKnQHsRmEFowFcXW7D4KRHDQzCf8RJStF3SVVGA1pTL"
  }
}

The IPNS link of the machine is then updated to point to the CID of this new document. This is all done automatically by the Radicle daemon.

Of course, only the owner of the IPNS link (the person who knows the private key paired to the public key the IPNS name is derived from) can update the IPNS link. So how do other people add inputs to a machine?

For this, the Radicle daemon uses IPFSPubsub, an experimental feature of IPFS. When a follower of a machine would like to add an expression, they publish this expression to the pubsub topic associated to the machine (this is just the machine's name). The Radicle daemon of the machine's owner will subscribe to this topic to listen for suggested inputs, and will accept any that is valid (doesn't cause an error). Once the expression is accepted, an acknowledgement is sent back to the follower, and the machine's IPNS link is updated.

How querying works

When using a Radicle utilities, the utility queries the state of some machine by making requests to the Radicle daemon. For example rad-issue might need to know who the author of issue 5 is. To do this, it sends a query to the Radicle daemon, which is just an expression to be speculatively evaluated on the machine. Once the result is obtained, the expression (and the resulting state) is discarded. For example a utility could query machine 12D3KooWBdkbHsG35HpEegK4ecr2MU3Um61B3rqhiGmSBrEi6eKQ with the expression (lookup :author (issue-by-number 5)). The daemon will make sure the machine is loaded and up to date before evaluating the expression, and it will also subscribe for updates in order to remain up to date. This ensures that subsequent queries take very little time to complete.

When a daemon executes a query, it pins all the expressions it had to download from IPFS. Therefore querying a machine also has the effect of seeding it to other peers.

The Radicle language & how utilities are written

Radicle machines are just sequences of expressions of the Radicle language; a LISP heavily inspired by Scheme, modified to be fully deterministic and have the ability to restrict the validity of future inputs. The code forming a Radicle machine has two components:

  • The machine code, that is, the inputs of the Radicle state machine,
  • The UX code. This provides all the functionality that is needed to help users submit valid inputs and to visualise the current state of the machine. It isn't strictly necessary to use the Radicle language for this but doing so presents several advantages:
    • A perfect fit with the radicle data model: Being a LISP, it's very natural to create an manipulate Radicle expressions in Radicle itself.
    • Code sharing code between the UX and machine: Just like it's attractive to use the same language on the frontend and backend of a traditional web-app (e.g. Node/JS, Clojure/Clojurescript, etc.), using Radicle for the UX code allows one to re-use machine functions, validation logic, etc. that was already needed for the machine code.

For more information about the Radicle language, check out the Radicle Language Docs.

Background Processes

Radicle requires 2 background processes to be running: radicle-ipfs and radicle-daemon. These are described in greater details below.

If you have installed Radicle via the brew or debian packages, the necessary background processes should already be available as brew or systemd services respectively (see installation).

If you are experiencing problems with Radicle, you should check the status of these services.

On OSX run:

brew services list

to check the status of all running services. On Linux use the commands

systemctl --user status radicle-ipfs
systemctl --user status radicle-daemon

to check the status of the IPFS daemon and the radicle daemon respectively.

Radicle ipfs daemon

The Radicle IPFS daemon is the process that runs an IPFS daemon, bootstrapping to our own separate Radicle IPFS network. Since all Radicle data is written as IPFS objects, the Radicle daemon must communicate with the Radicle IPFS daemon to actually persist any data to disk and expose it on the IPFS network.

To run the radicle IPFS daemon manually:

rad daemon-ipfs

Radicle daemon

The Radicle daemon is what manages your Radicle State Machines, accepting valid Radicle expressions as inputs from Radicle utilities on your machine, or from other apps on the Radicle IPFS network.

To run the radicle daemon manually:

rad daemon-radicle

Limitations & Troubleshooting

CLI feedback

Clearing all machine history

Sometimes all the things you tried still don't seem to work.

If all else fails and you are having strange errors when starting daemons or running Radicle commands, you can try wiping all of your Radicle State Machine data with the following command:

rm -rf ~/.local/share/radicle/machines.json

P2P communication is slow

It may take a minute for rad issues and `rad patch submissions to propogate, which you might encounter when using their respective rad issues list and rad patch list commands. This happens because IPNS updates aren't propogated immediately. Faster P2P updates will be a priority in an upcoming release.

IPNS lifetime

Each machine is identified by an IPNS record which, if not republished, will last 24 hours at most. If the computer that owns the machine is offline or not running the IPFS daemon for longer than that period, other computers will not be able to resolve your machine, and so will fail to read it even if there is no new data. Some 30 minutes or so after coming back online, your daemon will automatically republish the record.

Besides being online more often, there currently is no solution to this problem. We plan to eventually increase the length of time IPNS records last.

Networking issues (firewall, NAT)

Many networks, such as cafés and offices, are behind a firewall or NAT. Depending on the exact configuration, this may not present a problem, but often it does. In particular, two computers that are behind an untraversable firewall or NAT will not be able to read data from, or write data to, one another.

Other radicle daemons - that are not behind such restricted networks - can function as relays for your machines. This means they'll replicate your data to their more easily-accessible network, and convey write requests to you if you can't receive them directly. By default, all daemons try to act as a relay for the machines they follow (i.e. have queried or written to in the past). A friend who decided to see what you were up to on a machine, for example, may thus also end up helping others be able to query or collaborate with you on that machine.

But friends go offline. Instead of relying on that, you can also ask certain publicly available servers, that are always on and online, to follow your machine. We provide some such servers. To use it, run:

rad replicate

From your repo directory.

This has the additional advantage of making your data available for reading when you're offline.

Replication & availability (cannot resolve RSMs)

Work in progress

git-ipfs limitations

Replication

Data is replicated across the IPFS network based on demand: as soon as someone requests a particular piece of data, the network tries to find peers which already have it, and downloads it from there. The more peers download the datum, the more replicas exist on the network, and the faster the data can be downloaded.

For git-ipfs, this means that after a push, the computer from which it was initiated needs to stay online until someone else pulls the latest changes. Otherwise, those changes are not visible to the network.

While RSMs can be requested to be replicated by a remote Radicle daemon by using the rad replicate command, this mechanism currently does not include git repositories. We hope to address this in a future release. Meanwhile, if you would like pushes to be replicated without your computer being online permanently, we recommend to employ a pinning service.


Storage Space and Network Bandwidth

Git repositories employ a compression technique called packfiles to store git objects efficiently. How exactly a packfile is constructed is subject to heuristics, which means that two git repositories may pack in two diffent ways. In the traditional client-server model of git, this detail is hidden: when a client pushes to or pulls from a server, both first negotiate which objects need to be transferred at all. What goes over the wire is then a packfile of just the difference required to bring the other side up-to-date.

In a peer-to-peer setting, however, we can't rely on the other side being online at the same time we want to push or pull. Also, there is no way to ensure the integrity of a packfile without first downloading it as a whole.

IPFS (or, more precisely, IPLD) works very similar to "loose" git objects: the address of an IPFS object (respectively block) is the hash of its contents, which in turn may link to other objects via their hashes. Unsurprisingly thus, the IPLD project has devised git storage on IPFS to use uncompressed loose git objects, which allows for a fairly efficient way to request a subset of the history of a git repository, leveraging the content-addressability of the objects.

As a consequence, however, the overall space required to store a git repository on the local ipfs daemon, and to replicate it over the network is at least one order of magitude higher than in the traditional client-server model.


Pushing Changes as a Collaborator

Similar to RSMs, we leverage IPNS to address the latest changes to a git repository stored on IPFS. As a consequence, only the owner of that particular IPNS name may update it to point to new refs. This is similar to a GitHub repository where only the owner has push access. The equivalent to GitHub's fork paradigm is to create another remote which points to a different IPNS name, or just the empty URL ipfs://, and pushing to that.

Note that this is mostly useful if you employ a pinning service, or want to collaborate with people synchronously. The rad patch utility allows you to share patches without the need for pushing them.

FAQ

Why Radicle

When looking at the peer-to-peer tech landscape, it’s common to see projects bootstrapping their own technology. P2P developer communities strive to be active users and advocates of the tools they create, but it can be difficult to move off of centralized platforms entirely, especially when organizations like Github still play an essential role in the open source ecosystem.

This desire for P2P communities to be using P2P tools more generally isn’t really new. Scuttlebutt has long discussions around new ideas of “teamware.” Projects like git-ssb and git-remote-ipld have existed for some time already.

Rather than thinking of solutions for decentralized code collaboration within the scope of a single P2P protocol, Radicle tries to take what it can learn from existing solutions in the ecosystem, using these technologies directly where possible, and build towards a compelling vision of a technology stack that enables open source communities to easily to develop decentralized code collaboration tools and applications.

Isn’t git already a distributed version control system?

Yes! Git as a VCS (version control system) allows for collaboration on software projects to be distributed across mutliple computers. Using git, repositories can be distributed via email, self-hosted services like Gitea, or through third-party platforms like GitHub or GitLab. These services all serve as a way to have a canonical source of truth for the state of a project.

However, most software development also requires some form of social coordination, notably, issues and proposals i.e. GitHub’s pull requests or GitLab’s merge requests. Radicle tries to take these aspects of code collaboration and create a distributed state management system simliar to git. The Radicle CLI sits right alongside git, bringing the benefits of local repository storage to project issues and proposals.

Radicle’s peer-to-peer model allows you to directly exchange repos, issues, and patch proposals with your collaborators, without a third party host.

Can I use Radicle with GitHub, GitLab, or another code hosting service?

Yes. The Radicle utilties function 100% independently of where you host your code, be it GitHub, GitLab, or IPFS. This means you can use Radicle for managing issues and code contributions and still continue to host your code on a service like GitHub.

Select how you’d like to host your code when initializing a Radicle project with the rad project init command, which will prompt you to select where you want to set your git remote.

The Radicle commands that interact with your source code (like proposing and merging patches), will call out directly to git under the hood. So if there are any problems, you can use the existing git commands for managing merge conflicts.

What is the difference between Radicle and other P2P projects like Dat or Scuttlebutt?

While taking inspiration from other P2P projects like ZeroNet, Dat, and Scuttlebutt — as well as making use of IPFS for data replication — Radicle’s design centers on creating peer-to-peer tools for open source software development.

That said, there are some conceptual differences between Radicle and the P2P protocols above that are worth noting.

Both Dat and IPFS are “data-centric,” and often you’ll hear them called “distributed file systems” for this reason. Both make use of content addressing and DHTs to index and discover data on the network.

Similarly, we might say Scuttlebutt is “people-centric,” where each person or device has a personal feed represented by a hash-linked list of cryptographically signed messages. Rather than using a DHT for discovery, the Scuttlebutt gossip protocol propagates data through the social network, where users replicate all messages from the feeds they follow.

In Radicle, everything is centered around peer-to-peer collaboration tooling. Phrased another way, Radicle is program-centric. These peer-to-peer programs, also known as Radicle State Machines or RSMs, use the model of a state machine represented by a hash-linked list of inputs that are sequentially applied to the initial program state.

Through one lens these RSMs look quite similar to Scuttlebutt feeds, where instead of feeds representing a chain of messages signed by a Scuttlebutt user, RSMs represent a chain of updates to the state of a Radicle program.

Unlike Scuttlebutt however, Radicle programs have no social graph to allow data to propagate throughout the network. Rather than relying on its own custom network and replication layer, Radicle uses IPFS as the peer-to-peer infrastructure on which to build Radicle programs. RSM updates are written as IPFS objects, using IPLD to link between these IPFS objects, and lastly we use IPNS to give us persistent identifiers for RSMs that resolve to the current state.

If I am a project owner, can I get updates from contributors if we are not online at the same time?

Currently the owner of the project must be online in order to receive any proposed RSM updates from a contributor. Once received and processed, these updates will be written to IPFS by the project owner, and made available to all users who follow that project.

To alleviate this, one workaround is to run Radicle from a server that will always be online, setting that radicle-daemon to be the project owner. However, this means that all issue management and merging of patch proposals must happen from that server.

We’re aware that this is not ideal from a usability perspective, and are currently investigating alternative ways to help with this problem.

Can I collaborate on a local area network without an internet connection?

LAN-only collaboration isn't supported yet. IPFS still needs to connect to outside bootstrap nodes in order to read and write data from the network so a direct connection to the internet is required.

Can I collaborate privately?

Radicle does not explicitly support private collaboration. All data, projects, and peer-to-peer communication is publicly available on the IPFS network to anyone who knows your project ID.

Can I use the Radicle collaboration utilities with my favorite editor?

Yes. rad issue and rad patch uses whichever text editor is set in the $EDITOR environment variable. Set your default editor with export EDITOR=vim by executing the command in your terminal or setting the $EDITOR environment variable in your .bash_profile.

Get involved

For general inquiries, chatter, or questions, the easiest ways to get in touch is on the #radicle IRC channel on Freenode, or via our dev mailing list.

While Radicle is alpha software we still use GitHub for development (though we'll transition to dogfooding Radicle soon). Issues and PRs welcome!

Lastly, the core Radicle team does weekly updates on Secure Scuttlebutt, which you can see by following the #radicle-weekly-updates channel. If you’re not a scuttlebutt user already, pop over to IRC and we can give you an invite to our own Scuttlebutt pub :)

Also note, all contributions to the Radicle project and interactions with the community should adhere to our code of conduct.