Introduction to the Filesystem
Urbit has its own revision-controlled filesystem, Clay. Clay is a typed, global,
referentially transparent namespace. An easy way to think about it is like typed
git with continuous sync.
The most common way to use Clay is to mount a Clay node in a Unix directory. The Urbit process will watch this directory and automatically record edits as changes, Dropbox style. The mounted directory is always at the root of your pier directory.
This quick-start guide will walk you through some common commands. Follow along
using your Dojo. When you get a
>= message after entering a command, the means
that the command was successful.
When developing it's a good idea to use a separate desk. Create a
desk based on the
|merge %sandbox ~your-urbit %home
our produces your ship-name, meaning that you can run the following
command instead of typing out the entire thing. Useful for comets, due to their
very long names.
|merge %sandbox our %home
Most of the time we want to use Clay from Unix. Mount the entire contents of
sandbox desk to Unix:
~your-urbit:dojo> |mount /=sandbox=
To explore the filesystem from inside Urbit
+cat are useful.
displays files in the current directory, and
+cat displays the contents of
We can use
% to mean "current directory." The result of the command below
is just like using
ls in a Unix terminal.
~your-urbit:dojo> +ls %
+cat % does the same thing. That's because everything in Clay,
including directories, is a file.
Let's explore the
/web directory of the
~your-urbit:dojo> +ls /=sandbox=/web
Let's see the contents of
~your-urbit:dojo> +cat /=sandbox=/web/md
Now let's navigate to that folder using
=dir, which is a like
cd in Unix.
~your-urbit:dojo> =dir /=sandbox=/web/md
Youl'll notice that your prompt is now
change back to our home directory, we use
=dir without any path.
Sync from your friend
%experiment desk to your
|sync %sandbox ~some-ship %experiment
If and when your sync is successful, you will receive a message:
activated sync from %experiment on ~some-ship to %sandbox
The ship that you sync from will get their own message indicating that you're both connected as peers:
; ~your-urbit is your neighbor.
A path in Clay is a list of URL-safe text, restricted to the characters
~. Formally this is a
meaning that each segment, delineated by
/, is of the
knot ASCII-text type.
In other words, paths are expressed as
/foo/bar/baz. File extensions are
separated from file names with
.. Extensions are syntactically
identical to subdirectories, except that they must terminate the path.
Paths begin with a piece of data called a
beak. A beak is formally a
(p=ship q=desk r=case); it has three components, and might look like
beak component is
ship, which is, as you might guess, the name of
an Urbit ship. The second component is
desk, which is a workspace meant to
contain other directories; the default desk is
%home. The third component is
case, which represents version information in various ways: date and time;
a version sequence, which is a value incremented by one whenever a file on the
desk is modified; or an arbitrary plaintext label.
You can find what your
beak is at any given moment by
% in the Dojo and looking at the first three results.
beaks because, unlike the current internet, the Urbit network uses a
global namespace. That means that a file named
example.hoon in the
directory on the
%home desk of your ship
~lodleb-ritrul would have a
universal address to anyone else on the network:
~lodleb-ritrul/home/186/gen/example.hoon. That, of
course, doesn't mean that everyone on the network has privileges to access that
The structure that combines a
beak with further path information is called a
% command, which we gestured at in the above section, represents the
relative path, which is the path where you are currently working. If your
working directory is just your home desk, indicated by the
~your-planet:dojo>, then running the command below will print your
beam information: your
beak, and a
~ that represents
the empty list since no path is present.
%s can be stacked to indicate one level further up in the hierarchy for each
%. Try the following command:
You'll probably notice that it only has your ship name and the empty list. The
%s abandoned the
case and the
desk information by moving
up twice the hierarchy.
There are no local relative paths.
/foo/bar must be written as
You don't need to write out the explicit path every time you want to reference
somewhere outside of your working directory. You can substitute
= for the
segments of a path.
Recall that a full address in the the Urbit namespace is a
/ship/desk/case/path. If you've switched to another desk before, you're
already familiar with substitution syntax:
~your-urbit:dojo> =dir /=sandbox=
The above command substitutes uses substitution to use your current
case; only the
desk argument, which is located between the other two, is
given something new. Without substitution, you would need to write:
~your-urbit:dojo> =dir /~your-urbit/home/85
Substitutions work the same way in
ship/desk/case part) and
paths. For example, if you are in the
/gen directory, you can reference a file
/app directory like below. (
+cat displays the contents of a file).
~your-urbit:dojo/home/gen> +cat /===/app/curl/hoon
Note what was substituted out, and note that we don't need to separate
If we changed our working directory to something called
/gen/gmail, we could
access a file called
~fasdul-balsev-lodleb-ritrul:dojo/home/gen/gmail> +cat /===/app/=/split/hoon
Because both paths share a directory named
/gmail at the same position in the
address hierarchy -- which, if you recall, is just a
list -- the above command
We can do the same thing between desks. If
%sandbox has been merged with
%home, the following command will produce the same results as the above
~your-urbit:dojo/home/gen/gmail> +cat /=sandbox=/app/=/split/hoon
Most commonly this is used to avoid having to know the current revision
number in the
Change the working directory with
=dir. It's our equivalent of the Unix
For example, the syntax to navigate to
~your-urbit:dojo> =dir /=gen=/ask
This command will turn your prompt into something like this:
=dir without anything else uses the null path, which returns you to
your home desk.
To go up levels in the path hierarchy, recall the relative path expression
%. Stacking them represents another level higher in the hierarchy than
the current working directory for each
% beyond the initial. The command below
brings you one level up:
~your-urbit:dojo/gen> =dir %%
|mount /clay/path [Unix-name]
clay-path at the Unix mount point
/web inside your pier directory.
|mount %/gen generators
/generators inside your pier directory.
|unmount [clay-path || Unix-name]
Unmount the path or name from Unix.
Unmounts the path
%/web from whatever name it was mounted as.
Unmounts the Unix path
|merge desk beak[, =gem strategy]
beak into a
desk using an optional merge
beak is a ship-desk-case triple, encoded as a
|merge %home-work /=home=, =gem %fine
%home-work using merge strategy
|merge %examples ~wacbex-ribmex %examples
%examples desk from
|sync desk plot [plot-desk]
Subscribe to continuous updates from remote
plot on local
plot-desk can specify the remote
desk name. When omitted it is
defaulted to being the same as
desk. Non-comet urbits have
|sync %home ~parent %kids automatically set up (where
~parent is the
planet that issued a moon, the star that issued a planet, or the galaxy
that issued a star).
|sync %home-local ~dozbud %home |sync %home ~doznec
|unsync desk plot [plot-desk]
Unsubscribe from updates from remote
plot on local
plot-desk. Arguments must match original
|unsync %home-local ~dozbud %home
|label desk name`
Label the current version of
|label %home release
%init - Used if it's the first commit to a desk. Also can be used to
"reinitialize" a desk -- revision numbers keep going up, but the new
revision isn't necessarily a descendent of the previously numbered
version, allowing merges to be rerun.
%this - Keep what's in Bob's desk, but join the ancestry.
%that - take what's in Alice's desk, but join the ancestry. This is
the reverse of
%this. This is different from
%init because the new
commit has both sides in its ancestry.
%fine - "fast-forward" merge. This succeeds if and only if one head is in the
ancestry of the other.
%meld - find the most recent common ancestor to
use as our merge base.
%meet merge only succeeds if the changes from the merge base to
Alice's head (hereafter, "Alice's changes") are in different files than
Bob's changes. In this case, the parents are both Alice's and Bob's
heads, and the data is the merge base plus Alice's changed files plus
Bob's changed files.
%mate merge attempts to merge changes to the same file when both
Alice and Bob change it. If the merge is clean, we use it; otherwise, we
fail. A merge between different types of changes -- for example,
deleting a file vs changing it -- is always a conflict. If we succeed,
the parents are both Alice's and Bob's heads, and the data is the merge
base plus Alice's changed files plus Bob's changed files plus the merged
%meld merge will succeed even if there are conflicts. If there are
conflicts in a file, then we use the merge base's version of that file,
and we produce a set of files with conflicts. The parents are both
Alice's and Bob's heads, and the data is the merge base plus Alice's
changed files plus Bob's changed files plus the successfully merged
files plus the merge base's version of the conflicting files.
%auto - meta-strategy. Check to see if Bob's desk exists, and if it
doesn't we use an
%init merge. Otherwise, we progressively try
%mate until one succeeds. If none succeed, we
merge Bob's desk into a scratch desk. Then, we merge Alice's desk into
the scratch desk with the
%meld option to force the merge. Finally, we
annotate any conflicts, if we know how.
+cat path [path ...]
Similar to Unix
+cat takes one or more
paths, and prints their
contents. If that
path is a file, the contents of the file is printed. If the
path terminates in a directory, the list of names at that path is produced.
Similar to Unix
+ls takes a single
Produces a list of names at the
~your-urbit:dojo> +cat %/our/home/gen/curl/hoon
Remove the data at
path must be a path to actual node, not a
|cp to from
Copy the file at
from into the path
|mv to from
Move the file at
from into the path
|mv is just a shorthand for
doesn't happen unless the