Cabal is a “experimental p2p community chat platform”. It’s fully distributed over the dat protocol. When you create a new chat area – something like a Slack – it allows anyone with the same key to post and view messages everywhere. When you post a message, everyone gets it and shares it with everyone else, so even when your computer drops off there will still be a coherent view of the data.
/Updated 2020-07-14 for cabal-core 5.0/
You’ll need at least two computers to really play with this. But we can simulate the situation by running a docker container as well as a local instance of the cabal cli client. We can then move that container (or at least the image) around to run it on a remote server if you don’t want to mess with anything on the remote machine. Lets first install it locally:
On the terminal
If you just want to play around you can use
npx, or install the cabal cli command using
npm install --global cabal. Either way, lets start up a new cabal chat.
Take a note of the cabal URI on the top right of the screen, we’ll use that to connect with later. Keep this window running and start up a new Terminal window. Type in a test message such as “this is the first message” (or something less banal). There are also slash commands available,
/help will list them. Change your display nickname with
/n local node or something like that.
This is optional, you can just repeat the same steps on the remote node if you want. I have this in a Docker container because I don’t want to install node on my remote server, but if you have you computers and aren’t anal about it its super simple to just install node and just run
npx cabal on them also.
I like keeping things in Docker containers when playing around so that no unnecessary packages get installed on the machine and the data files are nicely cleaned up when I exit out.
This is a very basic node-based Dockerfile. Cabal/Dat uses port
3282 to communicate, so we’ll need to expose and open that.
Then build like so:
Create a simple script to make it easier to run in the future. (Note I’m using
--network host here because I was having trouble getting dat to punch through the Docker networking/NAT stuff.)
This script is for running one off commands, and it throws away the container each time so you’ll lose the history. If you really wanted to use this for something more than an experiment you should mount the internal
/root/.cabal directory to a docker volume and/or not make it a temporary container.
Push the container to the repository using
docker push $USER/cabal, and then move everything to a different computer. Then run:
If all goes well, after a few moments of network dancing you should be able to see the original message you sent. Type away to see if things show up!
cabal-core in code
That’s super cool already, but lets go a little deep and start writing our own handlers to see what we can do with
cabal isn’t secure at all so we probably shouldn’t use this for anything real, but its a nifty way to communicate and discover without having to setup very much at all!
Printing out everything that is in a swarm
- First we create a
Cabalinstance with a storage directory and our key, using
cabel = Cabal(directoy,key)
- Then we connect it to the swarm to start replicating using
- Once the local database has been loaded and processed, the
cabal.ready()callback is called. Events received after this are new.
- We can watch peers join and disconnect using
- We can listen for new messages and topics using
- (We can also listen for messages just in a specific channel, not shown below)
- We can listen for new channels
cabal.channels.events.on( 'add' )
- We can get a current channel list using
- We can listen for new nicknames using
Here’s it in code form
Now lets restart everything and see what happens! When I start up
node dump.js key on my machine, and then start up the
cabal-cli client on the other machine and:
/n Will- change my nickname to Will
This is my new name
/join new channel
lets talk about this instead
/topic Serious Stuff
Publishing a message
Publishing a message involves appending to your local feed and then synchronizing to the swarm. Which means waiting for the swarm to connect, a peer to join, and then them downloading everything. We don’t really know how long it will take, and there’s no real way to guarantee that it will show up. But we want a CLI tool that will eventually return, and not sit around forever. Here’s the logic we’ll use:
- Initialize cabal and try to connect to the swarm
- Post the message to the local store
- Once we get a peer connect message, wait 2 seconds for syncing and return success
- If we don’t get a peer connect in 10 seconds, then exit with error code.
Of course, if you just want to publish a message and serve the swarm forever, we could just take out the timeouts.
Then try running this code with a running cabal node on the remote host and without one. You’ll notice that the messages that were stored locally will eventually be delivered once a connection is made.
One thing that I’m interested in playing around with is using this as a message bus of sorts, to each have remote devices report in on what they are doing (raspberry pi’s for example) or be able to script it, to have a bot listening that takes commands in and run actions on the server and then pushes the results out (to IPFS for example.) But that’s for another post.