diff --git a/gen/hood/begin.hoon b/gen/hood/begin.hoon
index efc0ae5fb..301bda1cb 100644
--- a/gen/hood/begin.hoon
+++ b/gen/hood/begin.hoon
@@ -21,7 +21,7 @@
?~ +.arg -
(fun.q.q tic.arg)
%+ sole-lo
- [%& %helm-begin "your ship: ~"]
+ [%& %helm-begin "your urbit: ~"]
%+ sole-go fed:ag
|= his=@p
%+ sole-lo
diff --git a/gen/hood/cancel.hoon b/gen/hood/cancel.hoon
new file mode 100644
index 000000000..831d7469c
--- /dev/null
+++ b/gen/hood/cancel.hoon
@@ -0,0 +1,13 @@
+::
+:::: /hoon/cancel/hood/gen
+ ::
+/? 314
+::
+::::
+ !:
+:- %say
+|= $: [now=@da eny=@uvI bec=beak]
+ [[syd=@tas ~] ~]
+ ==
+:- %kiln-cancel
+syd
diff --git a/lib/base.css b/lib/base.css
index 6a5cd5955..94fae6346 100644
--- a/lib/base.css
+++ b/lib/base.css
@@ -70,552 +70,113 @@
font-weight: 500;
font-style: normal;
}
-body,
-html {
- font-family: "bau", "Helvetica Neue", helvetica, arial, sans-serif;
+@font-face {
+ font-family: "scp";
+ src: url("//storage.googleapis.com/urbit-extra/scp-bold.woff");
+ font-weight: 600;
+ font-style: normal;
}
-code,
-pre,
-li:before,
-.spin,
-#bred a,
-h3.time {
- font-family: "scp", "Courier New", courier, monospace;
+@font-face {
+ font-family: "scp";
+ src: url("//storage.googleapis.com/urbit-extra/scp-black.woff");
+ font-weight: 700;
+ font-style: normal;
}
-body,
-html {
- font-size: 18px;
- font-weight: 400;
- line-height: 1.6rem;
- -webkit-text-size-adjust: none;
-}
-a {
- color: #000;
- text-decoration: none;
- border-bottom: 2px solid #000;
- display: inline-block;
- line-height: 0.8rem;
-}
-hr {
- display: inline-block;
- width: 6rem;
- border: 0;
- border-top: 2px solid #f4f4f4;
-}
-h1 {
- margin-top: 4rem;
-}
-h2,
-h3 {
+
+html,
+body {
margin: 0;
- margin-top: 2rem;
-}
-h1,
-h2,
-h3,
-h4,
-strong {
- font-weight: 500;
-}
-h4 {
- margin-bottom: 0.3rem;
-}
-h5 {
- font-style: italic;
- font-weight: 200;
- margin: 0;
-}
-h1 code,
-h2 code,
-h3 code {
- font-size: inherit;
- padding: 0.3rem;
-}
-pre,
-code {
- font-size: 0.8rem;
-}
-pre {
- background-color: #f5f5f5;
- padding: 0.3rem;
- margin-left: -0.3rem;
-}
-code {
- line-height: 1.2rem;
- background-color: #f4f4f4;
- margin-top: -0.05rem;
- padding: 0.2rem;
- display: inline-block;
-}
-ul {
- list-style: none;
padding: 0;
}
-li:before {
- content: "+";
- padding-right: 0.3rem;
- font-size: 0.8rem;
- font-weight: 600;
+
+html,
+input,
+button,
+body {
+ font-family: "bau";
+ font-size: 18px;
}
-#nav,
-#cont {
+
+pre,
+code,
+.mono {
+ font-family:"scp";
+}
+
+#c {
+ width: 32rem;
+ margin-left: -16rem;
+ position: absolute;
left: 50%;
}
-#cont {
- width: 42rem;
- margin-left: -21rem;
- background-color: #fff;
- z-index: 1;
-}
-#nav {
- position: fixed;
- top: 0rem;
- width: 57rem;
- padding-top: 1rem;
- z-index: 0;
- margin-left: -32rem;
- overflow: hidden;
- opacity: 0;
- transition: opacity 1s ease-in-out;
-}
-#nav.moving {
- opacity: 1;
- transition: opacity 0.3s ease-in-out;
-}
-#nav:hover {
- opacity: 1;
- transition: opacity 0.3s ease-in-out;
-}
-#cont {
- position: absolute;
- top: 0;
- margin-bottom: 9rem;
-}
-.loading {
- display: inline-block;
-}
-.spin {
- color: #fff;
- padding: 0.6rem;
- font-size: 0.7rem;
- font-weight: 600;
- letter-spacing: 0.1rem;
- z-index: 3;
-}
-.loading > .spin {
- background-color: #555;
-}
-#body .loading > .spin {
- background-color: #000;
-}
-.spin.state-0:before {
- content: "\2599";
-}
-.spin.state-1:before {
- content: "\259B";
-}
-.spin.state-2:before {
- content: "\259C";
-}
-.spin.state-3:before {
- content: "\259F";
-}
-#load.load {
- display: inline-block;
- font-weight: 500;
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(10,10,10,0.4);
- opacity: 1;
- transition: opacity 1s ease-in-out;
- z-index: 4;
-}
-img.logo {
- height: 2rem;
- width: 2rem;
-}
-h3.time {
- margin-top: 0.3rem;
- font-size: 0.7rem;
- font-weight: 200;
-}
-#nav .links > div {
- display: inline-block;
- vertical-align: top;
-}
-#nav #sibs {
- width: 8rem;
- transition: margin-top 0.3s ease-in-out;
- overflow: hidden;
-}
-#nav #sibs > div {
- height: 20px;
- margin-bottom: 4px;
-}
-.focus #sibs {
- margin-top: 0 !important;
- transition: margin-top 0.3s ease-in-out;
-}
-#nav a,
-.list > li > a {
- text-transform: uppercase;
- font-size: 0.7rem;
- font-weight: 200;
- letter-spacing: 1px;
- white-space: nowrap;
-}
-.list > li > a {
- border-bottom: none;
- margin-bottom: 0.3rem;
-}
-#nav a,
-.list > li > a h1 {
- border-bottom: 1px solid #000;
- margin-right: 0.3rem;
-}
-#nav .active a {
- font-weight: 500;
- text-decoration: none;
-}
-#up {
- padding-right: 1rem;
- margin-top: -0.3rem;
-}
-#sides {
- float: right;
-}
-#sides a {
- margin-right: 0.6rem;
-}
-#nav .arow-up,
-#nav .arow-next,
-#nav .arow-prev {
- width: 0;
- height: 0;
- border: 0.4rem solid transparent;
-}
-#nav .arow-up {
- border-bottom: 0.6rem solid #000;
-}
-#nav .arow-next {
- border-left: 0.6rem solid #000;
-}
-#nav .arow-prev {
- border-right: 0.6rem solid #000;
-}
-#bred {
- width: 5rem;
- padding-right: 1rem;
- text-align: right;
- font-size: 0.6rem;
- white-space: nowrap;
- overflow: hidden;
-}
-#bred a {
- text-transform: lowercase;
- vertical-align: top;
-}
-#bred > div {
- float: right;
-}
-#bred > div > div {
- display: inline-block;
- margin-top: -0.2rem;
-}
-#bred a,
-#kids a {
- margin-right: 0.3rem;
-}
-#bred a {
- margin-left: 0.3rem;
-}
-.short {
- width: 32rem;
-}
-.list h1,
-.list li a > div p {
- margin: 0;
-}
-.list li a > div,
-.list li a > div p {
- display: inline;
-}
-.list li a > div p {
- margin-left: 0.3rem;
-}
-.list li a > div p:first-child {
- margin-left: 0;
-}
-.list li a > div p code {
- font-size: 0.7rem;
- font-weight: 400;
- text-transform: none;
-}
-.list li a h1 code {
- text-transform: lowercase;
- border-bottom: 1px solid #000;
-}
-.list li a code {
- padding: 0.2rem;
-}
-.list h1,
-.list li a > div div {
- display: inline;
-}
-.list li a > div div {
- margin-left: 0.6rem;
- overflow: hidden;
-}
-.list h1 {
- font-size: 0.7rem;
-}
-.list.posts .post {
- margin-bottom: 2rem;
-}
-.list.posts .post h1 {
- text-transform: none;
+
+h1 {
font-size: 1.6rem;
- line-height: 1.8rem;
- margin-bottom: 1rem;
- display: block;
-}
-.list.posts .post h2 {
- font-size: 0.7rem;
- font-weight: 400;
- line-height: 1rem;
- margin-top: 0;
-}
-.list.posts li.post:before {
- content: "";
-}
-div.root h1 {
- margin-bottom: 2rem;
-}
-div.root .list .sub {
- margin-left: 0;
- margin-right: 0.6rem;
-}
-div.root > p {
- width: 27rem;
- margin-top: 2rem;
-}
-h2.sub {
- font-size: 0.7rem;
- font-weight: 400;
- line-height: 1rem;
- letter-spacing: 1px;
- margin-top: 0;
- text-transform: uppercase;
-}
-div.post h1 {
- font-size: 2.8rem;
- line-height: 4rem;
- display: block;
- margin-top: 1rem;
- margin-bottom: 1rem;
-}
-div.post h2 {
- line-height: 1rem;
- letter-spacing: 1px;
-}
-div.post h2 {
- margin-top: 4rem;
-}
-div.post h2 {
- font-size: 1.2rem;
font-weight: 500;
}
-div.post p {
- font-size: 1.2rem;
- line-height: 2.2rem;
-}
-div.post li p {
- display: inline;
-}
-div.toc {
- margin-top: 3rem;
- margin-bottom: 3rem;
-}
-div.toc h1,
-div.toc h2,
-div.toc h3,
-div.toc h4 {
- font-weight: 400;
- cursor: pointer;
- text-decoration: underline;
- font-size: 1.2rem;
- margin-top: 0.3rem;
- margin-bottom: 0.3rem;
-}
-div.toc h2 {
+
+h1:after {
+ content: "\2014";
margin-left: 1rem;
}
-div.toc h3 {
- margin-left: 2rem;
+
+#c pre {
+ font-size: .6rem;
+ margin-top: 2rem;
}
-div.toc h4 {
- margin-left: 3rem;
+
+#pass {
+ width: 32rem;
}
-div.toc h1.t {
- font-weight: 500;
- font-size: 2rem;
- text-decoration: none;
- margin-bottom: 2rem;
-}
-#body .CodeMirror {
- font-size: 0.8rem;
- line-height: 1rem;
-}
-#body .CodeMirror .cm-header {
- font-weight: 200;
-}
-#body .CodeMirror-gutters {
+
+button {
+ border: .3rem solid #000;
background-color: #fff;
- padding-right: 1rem;
- margin-left: -1rem;
-}
-.error {
- color: #f91733;
-}
-.warning {
- background-color: #ff3537;
- padding: 1rem;
- width: 18rem;
- margin: 2rem 0;
- color: #fff;
-}
-.warning a {
- color: inherit;
- border-color: #fff;
-}
-.warning h1 {
font-size: 1rem;
+ padding: .3rem;
+ font-weight: 500;
}
-.warning h1,
-.warning p {
- margin: 0 0.3rem;
+
+.sig {
+ font-weight: 400;
+ font-size: 2rem;
+ display: inline;
+ vertical-align: middle;
}
-.warning.w {
- width: auto;
+
+span#ship {
+ font-family: 'bau';
+ font-weight: 400;
+ font-size: 1.2rem;
+ text-transform: uppercase;
+ letter-spacing: .1rem;
+ display: inline-block;
+ min-width: 1rem;
}
-@media only screen and (max-width: 1170px) {
- #nav,
- #nav > div,
- #nav.up,
- #nav.top,
- #nav > .focus {
- transform: translate3d(0, 0, 0);
- -webkit-transform: translate3d(0, 0, 0);
- }
- #nav {
- position: fixed;
- top: 0;
- opacity: 1;
- width: 42rem;
- margin-left: -21rem;
- background-color: #fff;
- z-index: 2;
- }
- #nav.m-down,
- #nav.m-up {
- position: absolute;
- }
- #nav.m-down.m-fixed {
- position: fixed;
- top: 0;
- }
- #nav > div {
- max-height: 1rem;
- overflow: hidden;
- transition: max-height 0.3s ease-in-out;
- }
- #nav > .focus {
- max-height: 40rem;
- transition: max-height 0.3s ease-in-out;
- }
- #cont {
- top: 3rem;
- }
+
+input {
+ font-family: 'scp';
+ display: inline;
}
-@media only screen and (min-width: 320px) and (max-width: 1024px) {
- body,
- html {
- font-size: 21px;
- }
- #nav,
- #cont {
- width: 94%;
- padding-left: 3%;
- margin-left: 0;
- }
- #nav {
- position: fixed;
- padding-top: 0;
- opacity: 1;
- left: 0;
- background-color: #fff;
- z-index: 2;
- }
- #nav > div {
- max-height: 1.4rem;
- }
- #nav > div {
- padding-top: 0.6rem;
- }
- #nav #sibs {
- width: 18rem;
- }
- #nav #sibs > div {
- height: 20px;
- line-height: 20px;
- }
- #nav a {
- display: inline-block;
- font-size: 0.7rem;
- }
- #nav #sides {
- float: right;
- }
- #nav .arow-up,
- #nav .arow-next,
- #nav .arow-prev {
- margin-right: 0;
- border: 0.4rem solid transparent;
- }
- #nav .arow-up {
- border-bottom: 0.6rem solid #000;
- }
- #nav .arow-next {
- border-left: 0.6rem solid #000;
- }
- #nav .arow-prev {
- margin-right: 1rem;
- border-right: 0.6rem solid #000;
- }
- #cont {
- top: 3rem;
- left: 0;
- padding-bottom: 9rem;
- }
- #cont h1:first-child {
- margin-top: 0;
- }
- .short {
- width: 100%;
- }
+
+span#ship,
+input {
+ border: none;
+ padding: .3rem;
+ outline: none;
+ border-bottom: 3px solid #555;
}
+
@media only screen and (min-device-width: 320px) and (max-device-width: 480px) {
- #nav > div {
- max-height: 1.6rem;
+ #c {
+ width: 16rem;
+ margin-left: -8rem;
}
- #nav a {
- font-size: 0.7rem;
+ #pass {
+ width: 16rem;
}
- #nav #sibs > div {
- height: 20px;
- line-height: 20px;
+ input {
+ -webkit-appearance: none;
+ border-radius: 0;
}
}
\ No newline at end of file
diff --git a/pub/doc.md b/pub/doc.md
index 94b4ab1ac..1f0a366ca 100644
--- a/pub/doc.md
+++ b/pub/doc.md
@@ -1,7 +1,7 @@
-urbit
-=====
+Urbit Manual
+============
-is a general-purpose computing stack designed to live in the cloud.
+Urbit is a general-purpose computing stack designed to live in the cloud.
@@ -11,6 +11,4 @@ is a general-purpose computing stack designed to live in the cloud.
------------------------------------------------------------------------
-If you're new to the system, take a look at some of the
-[guides](doc/guide) to get oriented. Come join us on `:talk` in the
-`/urbit-meta` channel to ask questions and get help.
+Come join us on `:talk` in the `/urbit-meta` channel to ask questions and get help.
diff --git a/pub/doc/arvo.md b/pub/doc/arvo.mdy
similarity index 99%
rename from pub/doc/arvo.md
rename to pub/doc/arvo.mdy
index 961231efc..3ca61fa60 100644
--- a/pub/doc/arvo.md
+++ b/pub/doc/arvo.mdy
@@ -1,3 +1,7 @@
+---
+sort: 2
+---
+
arvo
====
diff --git a/pub/doc/arvo/ives.md b/pub/doc/arvo/ives.md
deleted file mode 100644
index 5eb8907d9..000000000
--- a/pub/doc/arvo/ives.md
+++ /dev/null
@@ -1,8 +0,0 @@
-
hoon
diff --git a/pub/doc/hoon/reference/pronunciation.md b/pub/doc/hoon/reference/pronunciation.md
new file mode 100644
index 000000000..f7b4fab9a
--- /dev/null
+++ b/pub/doc/hoon/reference/pronunciation.md
@@ -0,0 +1,68 @@
+Pronunciation
+=============
+
+Overview
+--------
+
+Hoon is a reserved-word-free
+language - any text in the program is part of the program.
+
+We use so many of these ASCII glyphs that we like to be able
+to read them out loud. A language is meant to be _said_. The
+squiggles have conventional names, sort of, some of them easy to
+say, others not so much. So we've renamed them:
+
+ ace space
+ bar |
+ bas \
+ buc $
+ cab _
+ cen %
+ col :
+ com ,
+ doq "
+ dot .
+ fas /
+ gal <
+ gar >
+ hax #
+ hep -
+ kel {
+ ker }
+ ket ^
+ lus +
+ pam &
+ pat @
+ pel (
+ per )
+ sel [
+ sem ;
+ ser ]
+ sig ~
+ soq '
+ tar *
+ tec `
+ tis =
+ wut ?
+ zap !
+
+Memorizing these names seems like a burden, but it actually makes
+communicating about hoon code a lot faster and easier. `bartis`
+sounds a lot better than 'bar equals'.
+
+To pronounce a rune, concatenate the glyph names, stressing the
+first syllable and softening the second vowel into a "schwa."
+Hence, to say `~.`, say "sigdot." To say `|=`, say "bartis."
+Which has an inevitable tendency to turn into "barts" - a sin
+to be encouraged.
+
+There are a few runes with irregular special pronunciations:
+
+ -- hephep phep
+ +- lushep slep
+ ++ luslus slus
+ == tistis stet
+ +< lusgal glus
+ +> lusgar gras
+ -< hepgal gelp
+ -> hepgar garp
diff --git a/pub/doc/hoon/tutorial.md b/pub/doc/hoon/tutorial.md
new file mode 100644
index 000000000..1048ccb96
--- /dev/null
+++ b/pub/doc/hoon/tutorial.md
@@ -0,0 +1,4 @@
+Tutorials
+=========
+
+
\ No newline at end of file
diff --git a/pub/doc/hoon/tutorial/0-nouns.md b/pub/doc/hoon/tutorial/0-nouns.md
new file mode 100644
index 000000000..3dec5abd4
--- /dev/null
+++ b/pub/doc/hoon/tutorial/0-nouns.md
@@ -0,0 +1,232 @@
+# Hoon 0: introduction
+
+Hoon is a strict, higher-order typed pure-functional language.
+
+Why Hoon? On the one hand, typed functional languages are known
+for a particularly pleasant phenomenon: once your code compiles,
+it's quite likely to work. On the other hand, most typed
+functional languages are influenced by advanced mathematics.
+As Barbie once put it, math class is hard.
+
+Hoon is a typed FP language for the common street programmer.
+Well-written Hoon is as concrete and data-oriented as possible.
+The less functional magic you use, the better. One Haskell
+hacker described Hoon as "imperative programming in a functional
+language." He didn't mean this as a compliment, but we choose to
+take it as one.
+
+Moreover, one task of a type system in network computing is
+marshalling typed data on the sender, and validating untrusted
+data on the receiver. Hoon is very good at this task, which in
+most typed languages is an afterthought at best.
+
+The main disadvantage of Hoon is that its syntax and semantics
+are unfamiliar. The syntax will remind too many of Perl, but
+like most human languages (and unlike Perl) it combines a regular
+core structure with irregular variations. Its semantic
+complexity is bounded by the fact that the compiler is only 2000
+lines of Hoon (admittedly an expressive language). Most peoples'
+experience is that Hoon is much easier to learn than it looks.
+
+## Nouns: data made boring
+
+A noun is an atom or a cell. An atom is any unsigned integer. A
+cell is an ordered pair of nouns.
+
+The noun is an intentionally boring data model. Nouns (at least,
+nouns in Urbit) don't have cycles (although a noun implementation
+should take advantage of acyclic graph structure). Noun
+comparison is always by value (there is no way for the programmer
+to test pointer equality). Nouns are strict; there is no such
+thing as an infinite noun. And, of course, nouns are immutable.
+So there's basically no way to have any real fun with nouns.
+
+For language historians, nouns are Lisp's S-expressions, minus a
+lot of hacks, tricks, and features that made sense 50 years ago.
+In particular, because atoms are not tagged (an atom can encode a
+string, for instance), nouns work best with a static type system.
+How do you print an atom if you don't know whether it's a string
+or a number? You can guess, but...
+
+## A type system for nouns
+
+So learning nouns in practice involves learning them with a type
+system that makes them usable. Fortunately, we have that.
+
+One obstacle to learning Hoon is that it has two quite distinct
+concepts that might equally be called a "type." Worse, most
+other typed functional languages are mathy and share a basically
+mathematical concept of "type." We can't avoid using the T-word
+occasionally, but it has no precise meaning in Hoon and can be
+extremely confusing.
+
+Hoon's two kinds of "type" are `span` and `mold`. A span is both
+a constructively defined set of nouns, and a semantic convention
+for users in that set. A `mold` is a function whose range is
+some useful span. A mold is always idempotent (for any noun x,
+`f(x)` equals `f(f(x))`), and its domain is any noun.
+
+(One way to explain this is that while a span is what most
+languages call a "type," Hoon has no way for the programmer to
+express a span directly. Instead, we use inference to define it
+as the range of a function. This same function, the mold, can
+also be used to validate or normalize untrusted, untyped data --
+a common problem in modern programming.)
+
+(Hoon's inference algorithm is somewhat dumber than the
+unification algorithms (Hindley-Milner) used in most typed
+functional languages. Hoon reasons only forward, not backward.
+It needs more manual annotations, which you usually want anyway.
+Otherwise, it gets more or less the same job done.)
+
+## Let's make some nouns
+
+This stuff isn't even slightly hard. Let's make a noun:
+```
+~tasfyn-partyv:dojo> 42
+```
+You'll see the expression you entered, then the resulting value:
+```
+> 42
+42
+```
+Let's try a different value:
+```
+~tasfyn-partyv:dojo> 0x2a
+```
+You'll see:
+```
+> 0x2a
+0x2a
+```
+`42` and `0x2a` are actually *the same noun*, because they're the
+same number. But we don't just have the noun to print - we have
+a `[span noun]` cell (sometimes called a `vase`).
+
+As you recall, a span defines a set of nouns and a semantic
+interpretation. As sets, both spans here are "any number". But
+semantically, `42` has a decimal span and `0x2a` hexadecimal, so
+they print differently.
+
+(It's important to note that Hoon is a statically typed language.
+We don't work with vases unless we're dynamically compiling code,
+which is of course what we're doing here in the shell. Dynamic
+type is static type compiled at runtime.)
+
+Finally, let's make some cells. Try these on your own ship:
+```
+~tasfyn-partyv:dojo> [42 0x2a]
+~tasfyn-partyv:dojo> [42 [0x2a 420]]
+~tasfyn-partyv:dojo> [42 0x2a 420]
+```
+We observe that cells associate right: `[a b c]` is just another
+way of writing `[a [b c]]`.
+
+Also, Lisp veterans beware: Hoon `[a b]` is Lisp `(a . b)`, Lisp
+`(a b)` is Hoon `[a b ~]`(`~` represents nil, with a value of atom `0`). Lisp and Hoon are both pair-oriented
+languages down below, but Lisp has a layer of sugar that makes it
+look list-oriented. Hoon loves its "improper lists," ie, tuples.
+
+## Looking at spans
+
+What are these mysterious spans? We can see them with the `?`
+prefix, which prints the span along with the result. Moving to
+a more compact example format:
+```
+~tasfyn-partyv:dojo> ? 42
+ @ud
+42
+~tasfyn-partyv:dojo> ? 0x2a
+ @ux
+0x2a
+```
+`@ud` and `@ux` stand for "unsigned decimal" and "unsigned hex,"
+obviously. But what is this syntax?
+
+We only derive spans through inference. So there's no language
+syntax for a span. We have to be able to print spans, though, if
+only for debugging and diagnostics. `@ud` is an print-only
+syntax. (In this case it happens to be the same as the `mold`
+syntax, but that's just a coincidence.)
+
+## Looking at spans, part 2
+
+A good way to teach yourself to think in nouns is to look not at
+the prettyprinted span, but at the actual noun it's made of.
+Since everything in Hoon is a noun, a span is a noun too. When
+we use `??` rather than `?` as a prefix, we see the noun:
+```
+~tasfyn-partyv:dojo> ?? 42
+ [%atom %ud]
+42
+~tasfyn-partyv:dojo> ?? [42 0x2a]
+ [%cell [%atom %ud] [%atom %ux]]
+[42 0x2a]
+```
+What is this `%atom` notation? Is it a real noun? Can anyone
+make one?
+```
+~tasfyn-partyv:dojo> %atom
+%atom
+~tasfyn-partyv:dojo> %foo
+%foo
+~tasfyn-partyv:dojo> [%foo %bar]
+[%foo %bar]
+```
+What if we look at the span?
+```
+~tasfyn-partyv:dojo> ? %foo
+ %foo
+%foo
+~tasfyn-partyv:dojo> ?? %foo
+ [%cube 7.303.014 %atom %tas]
+%foo
+```
+This takes a little bit of explaining. First of all, `7.303.014`
+is just the German (and Urbit) way of writing `7,303,014`, or the
+hexadecimal number `0x6f.6f66`, or the string "foo" as an
+unsigned integer. (It's much easier to work with large integers
+when the digits are grouped.) Second, remembering that cells
+nest right, `[%cube 7.303.014 %atom %tas]` is really `[%cube
+7.303.014 [%atom %tas]]`.
+
+A `%cube` span is a constant -- a set of one noun, the atom
+`7.303.014`. But we still need to know how to print that noun.
+In this case, it's an `[%atom %tas]`, ie, a text symbol.
+
+Cubes don't have to be symbols -- in fact, we can take the
+numbers we've just been using, and make them constants:
+```
+~tasfyn-partyv:dojo> %42
+%42
+~tasfyn-partyv:dojo> ? %42
+ %42
+%42
+~tasfyn-partyv:dojo> ?? %42
+ [%cube 42 %atom %ud]
+%42
+```
+
+## Our first mold
+
+After seeing a few span examples, are we ready to describe the
+set of all spans with a Hoon mold? Well, no, but let's try it
+anyway. Ignore the syntax (which we'll explain later; this is a
+tutorial, not a reference manual), and you'll get the idea:
+```
+++ span
+ $% [%atom @tas]
+ [%cell span span]
+ [%cube * span]
+ ==
+```
+This mold is not the entire definition of `span`, just the cases
+we've seen so far. In English, a valid span is either:
+
+- a cell with head `%atom`, and tail some symbol.
+- a cell with head `%cell`, and tail some pair of spans.
+- a cell with head `%cube`, and tail a noun-span pair.
+
+The head of a span is essentially the tag in a variant record,
+a pattern every programming language has. To use the noun, we
+look at the head and then decide what to do with the tail.
diff --git a/pub/doc/hoon/tutorial/1-twigs.md b/pub/doc/hoon/tutorial/1-twigs.md
new file mode 100644
index 000000000..9ae966536
--- /dev/null
+++ b/pub/doc/hoon/tutorial/1-twigs.md
@@ -0,0 +1,229 @@
+# Hoon 1: twigs and legs
+
+In the last chapter we learned how to make nouns. In this
+chapter we'll start programming a little.
+
+## Nock for Hoon programmers
+
+Hoon compiles itself to a pico-interpreter called Nock. This
+isn't the place to explain Nock (which is to Hoon much as
+assembly language is to C), but Nock is just a way to express a
+function as a noun.
+
+Specifically, you can think of Nock as a (Turing-complete)
+interpreter shaped like (pseudocode):
+```
+Nock(subject formula) => product
+```
+Your function is the noun `formula`. The input to the function
+is the noun `subject`. The output is `product`. If something
+about this seems complicated or even interesting, you may be
+misunderstanding it.
+
+## From Hoon to Nock
+
+The Hoon parser turns an source expression (even one as simple as
+`42` from the last chapter) into a noun called a `twig`. If you
+know what an AST is, a twig is an AST. (If you don't know what
+an AST is, it's not worth the student loans.)
+
+To simplify slightly, the Hoon compiler is shaped like:
+```
+Hoon(subject-span function-twig) => [product-span formula-nock]
+```
+Hoon, like Nock, is a *subject-oriented* language - your twig is
+always executed against one input noun, the subject. For any
+subject noun in `subject-span`, the compiler produces a Nock
+formula that computes `function-twig` on that subject, and a
+`product-span` that is the span of the product.
+
+(Pretty much no other language works this way. In a normal
+language, your code is executed against a scope, stack, or other
+variable context, which may not even be a regular user-level
+value. This change is one of the hardest things to understand
+about Hoon, mostly because it's hard to stay convinced that
+subject-oriented programming is as straightforward as it is.)
+
+## From constants to twigs
+
+In the last chapter we were entering degenerate twigs like `42`.
+Obviously this doesn't use the subject at all.
+
+Let's use the dojo variable facility (this is *not* Hoon syntax,
+just a dojo command) to make a test subject:
+```
+~tasfyn-partyv:dojo> =test [[[8 9] 5] [6 7]]
+```
+We can evaluate twigs against this subject with the Hoon `:`
+syntax (`a:b` uses the product of `b` as the subject of `a`).
+```
+~tasfyn-partyv:dojo> 42:test
+42
+```
+
+## Tree addressing
+
+The simplest twigs produce a subtree, or "leg", of the subject.
+A cell, of course, is a binary tree. The very simplest twig is
+`.`, which produces the root of the tree - the whole subject:
+```
+~tasfyn-partyv:dojo> .:test
+[[[8 9] 5] 6 7]
+```
+(If you're wondering why `[6 7]` got printed as `6 7`, remember
+that `[]` associates to the right.)
+
+Hoon has a simple tree addressing scheme (inherited from Nock):
+the root is `1`, the head of `n` is `2n`, the tail is `2n+1`.
+The twig syntax is `+n`. Hence:
+```
+~tasfyn-partyv:dojo> +1:test
+[[[8 9] 5] 6 7]
+```
+Our example is a sort of Hoon joke, not very funny:
+```
+~tasfyn-partyv:dojo> +2:test
+[[8 9] 5]
+~tasfyn-partyv:dojo> +3:test
+[6 7]
+~tasfyn-partyv:dojo> +4:test
+[8 9]
+~tasfyn-partyv:dojo> +5:test
+5
+~tasfyn-partyv:dojo> +6:test
+6
+~tasfyn-partyv:dojo> +7:test
+7
+```
+And so on. An instinct for binary tree geometry develops over
+time as you use the system, rather the way most programmers
+learn to do binary math.
+
+## Femur syntax
+
+A "femur" is an alternative syntax for a tree address. The femur
+syntax creates a recognizable geometric shape by alternating
+between two head/tail pairs, read left to right: `-` and `+`,
+`<` and `>`.
+
+Thus `-` is `+2`, `+` is `+3`, `+<` is `+6`, `->` is `+5`, `-<+`
+is `+9`, etc. The decimal numbers are distracting, whereas the
+glyph string binds directly to the tree geometry as you learn it.
+We actually almost never use the decimal tree geometry syntax.
+
+## Simple faces
+
+But it would be pretty tough to program in Hoon if explicit
+geometry was the only way of getting data out of a subject.
+Let's introduce some new syntax:
+```
+~tasfyn-partyv:dojo> foo=42
+foo=42
+~tasfyn-partyv:dojo> ? foo=42
+ foo=@ud
+foo=42
+~tasfyn-partyv:dojo> ?? foo=42
+ [%face %foo %atom %ud]
+foo=42
+```
+To extend our `++span` mold:
+```
+++ span
+ $% [%atom @tas]
+ [%cell span span]
+ [%cube * span]
+ [%face @tas span]
+ ==
+```
+The `%face` span wraps a label around a noun. Then we can
+get a leg by name. Let's make a new dojo variable:
+```
+~tasfyn-partyv:dojo> =test [[[8 9] 5] foo=[6 7]]
+```
+The syntax is what you might expect:
+```
+~tasfyn-partyv:dojo> foo:test
+[6 7]
+```
+Does this do what you expect it to do?
+```
+~tasfyn-partyv:dojo> +3:test
+foo=[6 7]
+~tasfyn-partyv:dojo> ? +3:test
+ foo=[@ud @ud]
+foo=[6 7]
+~tasfyn-partyv:dojo> ?? +3:test
+ [%face %foo %cell [%atom %ud] %atom %ud]
+foo=[6 7]
+```
+
+## Interesting faces; wings
+
+Again, you're probably used to name resolution in variable scopes
+and flat records, but not in trees. (Partly this is because the
+tradition in language design is to eschew semantics that make it
+hard to build simple symbol tables, because linear search of a
+big tree is a bad idea on '80s hardware.)
+
+Let's look at a few more interesting face cases. First, suppose
+we have two cases of `foo`?
+```
+~tasfyn-partyv:dojo> =test [[foo=[8 9] 5] foo=[6 7]]
+~tasfyn-partyv:dojo> foo:test
+[8 9]
+```
+In the tree search, the head wins. We can overcome this with a
+`^` prefix, which tells the search to skip its first hit:
+```
+~tasfyn-partyv:dojo> =test [[foo=[8 9] 5] foo=[6 7]]
+~tasfyn-partyv:dojo> ^foo:test
+[6 7]
+```
+`^^foo` will skip two foos, `^^^foo` three, up to `n`.
+But what about nested labels?
+```
+~tasfyn-partyv:dojo> =test [[[8 9] 5] foo=[6 bar=7]]
+~tasfyn-partyv:dojo> bar:test
+/~tasfyn-partyv/home/~2015.9.16..21.40.21..1aec:<[1 1].[1 9]>
+-find-limb.bar
+find-none
+```
+It didn't seem to like that. We'll need a nested search:
+```
+~tasfyn-partyv:dojo> bar.foo:test
+7
+```
+`bar.foo` here is a `wing`, a search path in a noun. Note that
+the wing runs from left to right, ie, the opposite of most
+languages: `bar.foo` means "bar inside foo."
+
+Each step in a wing is a `limb`. A limb can be a tree address,
+like `+3` or `.`, or a label like `foo`. We can combine them in
+one wing:
+```
+~tasfyn-partyv:dojo> bar.foo.+3:test
+7
+```
+
+## Mutation
+
+Well, not really. We can't modify nouns; the concept doesn't
+even make sense in Hoon. Rather, we build new nouns which are
+(logical -- the pointers are actually shared) copies of old ones,
+with changes.
+
+Let's build a "mutated" copy of our test noun:
+```
+~tasfyn-partyv:dojo> test
+[[[8 9] 5] foo=[6 bar=7]]
+~tasfyn-partyv:dojo> test(foo 42)
+[[[8 9] 5] foo=42]
+~tasfyn-partyv:dojo> test(+8 %eight, bar.foo [%hello %world])
+[[[%eight 9] 5] foo=[6 [%hello %world]]]
+```
+As we see, there's no obvious need for the mutant noun to be
+shaped anything like the old noun. They're different nouns.
+
+At this point, you have a simplified but basically sound idea of
+how Hoon builds and manages nouns. Next, it's time to do some
+programming.
diff --git a/pub/doc/hoon/tutorial/2-syntax.md b/pub/doc/hoon/tutorial/2-syntax.md
new file mode 100644
index 000000000..3864ba48c
--- /dev/null
+++ b/pub/doc/hoon/tutorial/2-syntax.md
@@ -0,0 +1,392 @@
+# Hoon 2: serious syntax
+
+We've done a bunch of fun stuff on the command line. We know our
+nouns. It's time to actually write some serious code -- in a
+real source file.
+
+## Building a simple generator
+
+In Urbit there's a variety of source file roles, distinguished by
+the magic paths they're loaded from: `/gen` for generators,
+`/ape` for appliances, `/fab` for renderers, etc.
+
+We'll start with a generator, the simplest kind of Urbit program.
+
+### Create a sandbox desk
+
+A desk is the Urbit equivalent of a `git` branch. We're just
+playing around here and don't intend to soil our `%home` desk with
+test files, so let's make a sandbox:
+```
+|merge %sandbox our %home
+```
+### Mount the sandbox
+
+Your Urbit pier is in `~/tasfyn-partyv`, or at least mine is.
+So we can get our code into Urbit, run the command
+```
+~tasfyn-partyv:dojo> |mount /=sandbox=/gen %gen
+```
+mounts the `/gen` folder from the `%sandbox` desk in your Unix
+directory `~/tasfyn-partyv/gen`. The mount is a two-way sync,
+like your Dropbox. When you edit a Unix file and save, your edit
+is automatically committed as a change to `%sandbox`.
+
+### Execute from the sandbox
+
+The `%sandbox` desk obviously is merged from `%home`, so it
+contains find all the default facilities you'd expect there.
+Bear in mind, we didn't set it to auto-update when `%home`
+is updated (that would be `|sync` instead of `|merge`).
+
+So we're not roughing it when we set the dojo to load from
+`%sandbox`:
+```
+[switch to %home]
+```
+
+### Write your builder
+
+Let's build the simplest possible kind of generator, a builder.
+With your favorite Unix text editor (there are Hoon modes for vim
+and emacs), create the file `~/tasfyn-partyv/gen/test.hoon`.
+Edit it into this:
+```
+:- %say |= * :- %noun
+[%hello %world]
+```
+Get the spaces exactly right, please. Hoon is not in general a
+whitespace-sensitive language, but the difference between one
+space and two-or-more matters. And for the moment, think of
+```
+:- %say |= * :- %noun
+```
+as gibberish boilerplate at the start of a file, like `#include
+"stdio.h"` at the start of a C program. Any of our old Hoon
+constants would work in place of `[%hello %world`].
+
+Now, run your builder:
+```
+~tasfyn-partyv:dojo/sandbox> +test
+[%hello %world]
+```
+Obviously this is your first Hoon *program* per se.
+
+## Hoon syntax 101
+
+But what's up with this syntax?
+
+### A syntactic apology
+
+The relationship between ASCII and human programming languages
+is like the relationship between the electric guitar and
+rock-and-roll. If it doesn't have a guitar, it's not rock.
+Some great rockers play three chords, like Johnny Ramone; some
+shred it up, like Jimmy Page.
+
+The two major families of ASCII-shredding languages are Perl and
+the even more spectacular APL. (Using non-ASCII characters is
+just a fail, but APL successors like J fixed this.) No one
+has any right to rag on Larry Wall or Ken Iverson, but Hoon,
+though it shreds, shreds very differently.
+
+The philosophical case for a "metalhead" language is threefold.
+One, human beings are much better at associating meaning with
+symbols than they think they are. Two, a programming language is
+a professional tool and not a plastic shovel for three-year-olds.
+
+And three, the alternative to heavy metal is keywords. When you
+use a keyword language, not only are you forcing the programmer
+to tiptoe around a ridiculous maze of restricted words used and
+reserved, you're expressing your program through two translation
+steps: symbol->English and English->computation. When you shred,
+you are going direct: symbol->computation. Especially in a pure
+language, this creates a sense of "seeing the function" which no
+keyword language can quite duplicate.
+
+But any metalhead language you don't yet know is line noise.
+Let's get you up to speed as fast as possible.
+
+### A glyphic bestiary
+
+A programming language needs to be not just read but said. But
+no one wants to say "ampersand." Therefore, we've taken the
+liberty of assigning three-letter names to all ASCII glyphs.
+
+Some of these bindings are obvious and some aren't. You'll be
+genuinely surprised at how easy they are to remember:
+```
+ ace [1 space] dot . pan ]
+ bar | fas / pel )
+ bis \ gap [>1 space, nl] pid }
+ buc $ hax # ran >
+ cab _ ket ^ rep '
+ cen % lep ( sac ;
+ col : lit < tar *
+ com , lus + tec `
+ das - mat @ tis =
+ den " med & wut ?
+ dip { nap [ zap !
+```
+It's fun to confuse people by using these outside Urbit. A few
+digraphs also have irregular sounds:
+```
+== stet
+-- shed
+++ slus
+-> dart
+-< dusk
++> lark
++< lush
+```
+
+### The shape of a twig
+
+A twig, of course, is a noun. As usual, the easiest way to
+explain both the syntax that compiles into that noun, and the
+semantic meaning of the noun, is the noun's physical structure.
+
+#### Autocons
+
+A twig is always a cell, and any cell of twigs is a twig
+producing a cell. As an homage to Lisp, we call this
+"autocons." Where you'd write `(cons a b)` in Lisp, you write
+`[a b]` in Hoon, and the shape of the twig follows.
+
+The `???` prefix prints a twig as a noun instead of running it.
+Let's see autocons in action:
+```
+~tasfyn-partyv:dojo/sandbox> ??? 42
+[%dtzy %ud 42]
+~tasfyn-partyv:dojo/sandbox> ??? 0x2a
+[%dtzy %ux 42]
+~tasfyn-partyv:dojo/sandbox> ??? [42 0xa]
+[[%dtzy %ud 42] %dtzy %ux 42]
+```
+(As always, it may confuse *you* that this is the same noun as
+`[[%dtzy %ud 42] [%dtzy %ux 42]]`, but it doesn't confuse Hoon.)
+
+#### The stem-bulb pattern
+
+If the head of your twig is a cell, it's an autocons. If the
+head is an atom, it's an unpronounceable four-letter symbol like
+the `%dtzy` above.
+
+This is the same pattern as we see in the `span` mold -- a
+variant record, essentially, in nouns. The head of one of these
+cells is called the "stem." The tail is the "bulb." The shape
+of the bulb is totally dependent on the value of the stem.
+
+#### Runes and stems
+
+A "rune" (a word intentionally chosen to annoy Go programmers) is
+a digraph - a sequence of two ASCII glyphs. If you know C, you
+know digraphs like `->` and `?:` and are used to reading them as
+single characters.
+
+In Hoon you can *say* them as words: "dasran" and "wattis"
+respectively. In a metalhead language, if we had to say
+"minus greater-than" and "question-colon", we'd just die.
+
+Most twig stems are made from runes, by concatenating the glyph
+names and removing the vowels. For example, the rune `=+`,
+pronounced "tislus," becomes the stem `%tsls`. (Note that in
+many noun implementations, this is a 31-bit direct value.)
+
+(Some stems (like `%dtzy`) are not runes, simply because they
+don't have regular-form syntax and don't need to use precious
+ASCII real estate. They are otherwise no different.)
+
+An important point to note about runes: they're organized. The
+first glyph in the rune defines a category. For instance, runes
+starting with `.` compute intrinsics; runes starting with `|`
+produce cores; etc.
+
+Another important point about runes: they come in two flavors,
+"natural" (stems interpreted directly by the compiler) and
+"synthetic" (macros, essentially).
+
+(Language food fight warning: one advantage of Hoon over Lisp is
+that all Hoon macros are inherently hygienic. Another advantage
+is that Hoon has no (user-level) macros. In Hoon terms, nobody
+gets to invent their own runes. A DSL is always and everywhere
+a write-only language. Hoon shreds its ASCII pretty hard, but
+the same squiggles mean the same things in everyone's code.)
+
+#### Wide and tall regular forms
+
+A good rune example is the simple rune `=+`, pronounced "tislus",
+which becomes the stem `%tsls`. A `%tsls` twig has the shape
+`[%tsls twig twig]`.
+
+The very elegance of functional languages creates a visual
+problem that imperative languages lack. An imperative language
+has distinct statements (with side effects) and (usually pure)
+expressions; it's natural that in most well-formatted code,
+statements flow vertically down the screen, and expressions grow
+horizontally across this. This interplay creates a natural and
+relaxing shape on your screen.
+
+In a functional language, there's no difference. The trivial
+functional syntax is Lisp's, which has two major problems. One:
+piles of expression terminators build up at the bottom of complex
+functions. Two: the natural shape of code is diagonal. The more
+complex a function, the more it wants to besiege the right
+margin. The children of a node have to start to the right of its
+parent, so the right margin bounds the tree depth.
+
+Hoon does not completely solve these problems, but alleviates
+them. In Hoon, there are actually two regular syntax forms for
+most twig cases: "tall" and "wide" form. Tall twigs can contain
+wide twigs, but not vice versa, so the visual shape of a program
+is very like that of a statements-and-expressions language.
+
+Also, in tall mode, most runes don't need terminators. Take
+`=+`, for example. Since the parser knows to expect exactly
+two twigs after the `=+` rune, it doesn't need any extra syntax
+to tell it that it's done.
+
+Let's try a wide `=+` in the dojo:
+```
+~tasfyn-partyv:dojo/sandbox> =+(planet=%world [%hello planet])
+[%hello %world]
+```
+(`=+` seems to be some sort of variable declaration? Let's not
+worry about it right now. We're on syntax.)
+
+The wide syntax for a `=+` twig, or any binary rune: `(`, the
+first subtwig, one space, the second subtwig, and `)`). To read
+this twig out loud, you'd say:
+```
+tislus lap planet is cen world ace nep cen hello ace planet pen
+pal
+```
+("tis" not in a rune gets contracted to "is".)
+
+Let's try a tall `=+` in `test.hoon`:
+```
+:- %say |= * :- %noun
+=+ planet=%world
+[%hello planet]
+```
+The tall syntax for a `=+` twig, or any binary rune: the rune, at
+least two spaces or one newline, the first subtwig, at least two
+spaces or one newline, the second subtwig. Again, tall subtwigs
+can be tall or wide; wide subtwigs have to be wide.
+
+(Note that our boilerplate line is a bunch of tall runes on one
+line, with two-space gaps. This is unusual but quite legal, and
+not to be confused with the actual wide form.)
+
+To read this twig out loud, you'd say:
+```
+tislus gap planet is cen world gap nep cen hello ace planet pen
+```
+#### Layout conventions
+
+Should you use wide twigs or tall twigs? When? How? What
+should your code look like? You're the artist. Except for the
+difference between one space (`ace`) and more space (`gap`), the
+parser doesn't care how you format your code. Hoon is not Go --
+there are no fixed rules for doing it right.
+
+However, the universal convention is to keep lines under 80
+characters. Also, hard tab characters are illegal. And when in
+doubt, make your code look like the kernel code.
+
+##### Backstep indentation
+
+Note that the "variable declaration" concept of `=+` (which is no
+more a variable declaration than a Tasmanian tiger is a tiger)
+works perfectly here. Because `[%hello planet]` -- despite being
+a subtree of the the `=+` twig -- is at the same indent level.
+So our code flows down the screen, not down and to the right, and
+of course there are no superfluous terminators. It looks good,
+and creates fewer hard-to-find syntax errors than you'd think.
+
+This is called "backstep" indentation. Another example, using a
+ternary rune that has a strange resemblance to C:
+```
+:- %say |= * :- %noun
+=+ planet=%world
+?: =(%world planet)
+ [%hello planet]
+[%goodbye planet]
+```
+It's not always the case when backstepping that the largest
+subtwig is at the bottom and loses no margin, but it often is.
+And not all runes have tuple structure; some are n-ary, and use
+the `==` terminator (again, pronounced "stet"):
+```
+:- %say |= * :- %noun
+=+ planet=%world
+?+ planet
+ [%unknown planet]
+ %world [%hello planet]
+ %ocean [%goodbye planet]
+==
+```
+So we occasionally lose right-margin as we descend a deep twig.
+But we can keep this lossage low with good layout design. The
+goal is to keep the heavy twigs on the right, and Hoon tries as
+hard as possible to help you with this.
+
+For instance, `=+` ("tislus") is a binary rune: `=+(a b)`. In
+most cases of `=+` the heavy twig is `b`, but sometimes it's `a`.
+So we can use its friend the `=-` rune ("tisdas") to get the same
+semantics with the right shape: `=-(b a)`.
+
+#### Irregular forms
+
+There are more regular forms than we've shown above, but not a
+lot more. Hoon would be quite easy to learn if it was only its
+regular forms. It wouldn't be as easy to read or use, though.
+The learning curve is important, but not all-important.
+
+Some stems (like the `%dtzy` constants above) obviously don't and
+can't have any kind of regular form (which is why `%dtzy` is not
+a real digraph rune). Many of the true runes have only regular
+forms. But some have irregular forms. Irregular forms are
+always wide, but there is no other constraint on their syntax.
+
+We've already encountered one of the irregular forms: `foo=42`
+from the last chapter, and `planet=%world` here. Let's unpack
+this twig:
+```
+~tasfyn-partyv:dojo/sandbox> ?? %world
+ [%cube 431.316.168.567 %atom %tas]
+%world
+
+~tasfyn-partyv:dojo/sandbox> ??? %world
+[%dtzz %tas 431.316.168.567]
+```
+Clearly, `%dtzz` is one of our non-regulars. But we can wrap it
+with our irregular form:
+```
+~tasfyn-partyv:dojo/sandbox> ?? planet=%world
+ [%face %planet [%cube 431.316.168.567 %atom %tas]]
+planet=%world
+
+~tasfyn-partyv:dojo/sandbox> ??? planet=%world
+[%ktts %planet %dtzz %tas 431.316.168.567]
+```
+Since `%ktts` is "kettis", ie, `^=`, this has to be the irregular
+form of
+```
+~tasfyn-partyv:dojo/sandbox> ^=(planet %world)
+planet=world
+```
+So if we wrote our example without this irregular form, it'd be
+```
+:- %say |= * :- %noun
+=+ ^=(planet %world)
+[%hello planet]
+```
+Or with a gratuitous use of tall form:
+```
+:- %say |= * :- %noun
+=+ ^= planet %world
+[%hello planet]
+```
+Now you know how to read Hoon! For fun, try to pronounce more of
+the code on this page. Please don't laugh too hard at yourself.
diff --git a/pub/doc/hoon/tutorial/3-program.md b/pub/doc/hoon/tutorial/3-program.md
new file mode 100644
index 000000000..964e62f16
--- /dev/null
+++ b/pub/doc/hoon/tutorial/3-program.md
@@ -0,0 +1,316 @@
+# Hoon 3: our first program
+
+It's time for us to do some actual programming. In this section,
+we'll work through that classic Urbit pons asinorum, decrement.
+
+If you learned Nock before Hoon, you've already done decrement.
+If not, all you need to know is that the only arithmetic
+intrinsic in Nock is increment -- in Hoon, the unary `.+` rune.
+So an actual decrement function is required.
+
+In chapter 3, we write a decrement builder: more or less the
+simplest nontrivial Urbit program. We should be able to run this
+example:
+```
+~tasfyn-partyv:dojo/sandbox> +test 42
+41
+```
+
+## What's in that subject?
+
+As we've seen, Hoon works by running a twig against a subject.
+We've been cheerfully running twigs through three chapters while
+avoiding the question: what's in the subject? To avoid the issue
+we've built a lot of constants, etc.
+
+Of course your twig's subject comes from whoever runs it. There
+is no one true subject. Our twigs on the command line are not
+run against the same subject as our generator code, even though
+they are both run by the same `:dojo` appliance.
+
+But the short answer is that both command-line and builder get
+*basically* the same subject: some ginormous noun containing all
+kinds of bells and whistles and slicers and dicers, including a
+kernel library which can needless to say decrement in its sleep.
+
+As yet you have only faced human-sized nouns. We need not yet
+acquaint you with this mighty Yggdrasil, Mother of Trees. First
+we need to figure out what she could even be made of.
+
+## Clearing the subject
+
+We'll start by clearing the subject:
+```
+:- %say |= * :- %noun
+=> ~
+[%hello %world]
+```
+The `=>` rune ("tisran"), for `=>(p q)` executes `p` against
+the subject, then uses that product as the subject of `q`.
+
+(We've already used an irregular form of `=>`, or to be more
+precise its mirror `=<` ("tislit"). In chapter 1, when we wrote
+`+3:test`, we meant `=>(test +3)` or `=<(+3 test)`.)
+
+What is this `~`? It's Hoon `nil`, a zero atom with this span:
+```
+~tasfyn-partyv:dojo/sandbox> ?? ~
+ [%cube 0 %atom %n]
+~
+```
+We use it for list terminators and the like. Obviously, since
+our old test code is just a constant, a null subject works fine:
+```
+~tasfyn-partyv:dojo/sandbox> +test
+[%hello %world]
+```
+
+## Getting an argument
+
+Obviously, if we want to write a decrement builder, we'll have to
+get an argument from the command line. This involves changing
+the `test.hoon` boilerplate a little:
+```
+:- %say |= [* [[arg=@ud ~] ~]] :- %noun
+=> arg=arg
+[%hello arg]
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+[%hello 42]
+```
+`=> arg=arg` looks a little odd. We wouldn't ordinarily do
+this. We're just replacing a very interesting subject that
+contains `arg` with a very boring one that contains only `arg`,
+for the same reason we cleared the subject with `~`.
+
+In case there's any doubt about the subject (`.` is limb syntax
+for `+1`, ie, the whole noun):
+```
+:- %say |= [* [[arg=@ud ~] ~]] :- %noun
+=> arg=arg
+.
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+arg=42
+```
+
+We can even write a trivial increment function using `.+`:
+```
+:- %say |= [* [[arg=@ud ~] ~]] :- %noun
+=> arg=arg
++(arg)
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+43
+```
+Below we'll skip both boilerplate lines in our examples.
+
+## A core is a code-data cell
+
+But how do we actually, like, code? The algorithm for decrement
+is clear. We need to count up to 41. (How do we run useful
+programs on a computer with O(n) decrement? That's an
+implementation detail.)
+
+We'll need another kind of noun: the *core*. Briefly, the core
+is always a cell `[battery payload]`. The payload is data, the
+battery is code -- one or more Nock formulas, to be exact.
+
+Consider a simple core with a one-formula battery. Remember, we
+create Nock formulas by compiling a twig against a subject. The
+subject is dynamic data, but its span is static. What span do we
+give the compiler, and what noun do we give the formula?
+
+A core formula always has the core as its subject. The formula
+is essentially a computed attribute on the payload. But if the
+subject was just the payload, the formula couldn't recurse.
+
+Of course, there is no need to restrict ourselves to one computed
+attribute. We can just stick a bunch of formulas together and
+call them a battery. The source twigs in this core are called
+"arms," which have labels just like the faces we saw earlier.
+
+Hoon overloads computed attributes (arms) and literal attributes
+(legs) in the same namespace. A label in a wing may refer to
+either. To extend the name-resolution tree search described in
+chapter 1, when searching a core, we look for a matching arm.
+If we find it we're done. If we don't, or if a `^` mark makes us
+skip, we search into the payload.
+
+If a name resolves to a core arm, but it's not the last limb in the
+wing, the arm produces the core itself. Similarly, when the
+wing is not an access but a mutation, the arm refers to the core.
+
+This demands an example: if `foo` produces some core `c`, and
+`bar` is an arm in that `c` (which may be `foo` itself, or some
+leg within `foo`), `bar.foo` runs the arm formula with `c` as the
+subject. You might think that `moo.bar.foo` would compute
+`bar.foo`, then search for `moo` within that result. Instead, it
+searches for `moo` within `c`. (You can get the other result
+with `moo:bar.foo`.)
+
+Does this sound too tricky? It should - it's about the most
+complicated feature of Hoon. It's all downhill once you
+understand cores.
+
+Let's again extend our `++span` mold:
+```
+++ span
+ $% [%atom @tas]
+ [%cell span span]
+ [%core span (map ,@tas twig)]
+ [%cube * span]
+ [%face @tas span]
+ ==
+```
+This definition of `%core` is somewhat simplified from the
+reality, but basically conveys it. (Moreover, this version of
+`span` describes every kind of noun we build.) In our `%core` we
+see a payload span and a name-to-twig arm table, as expected.
+
+Is a core an object? Not quite, because an arm is not a method.
+Methods in an OO language have arguments. Arms are functions
+only of the payload. (A method in Hoon is an arm that produces a
+gate, which is another core -- but we're getting too far ahead.)
+However, the battery does look a lot like a classic "vtable."
+
+## Increment with a core
+
+Let's increment with a core:
+```
+=< inc
+|%
+++ inc
+ +(arg)
+--
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+43
+```
+What's going on? We used the `|%` rune ("barcen") to produce a
+core. (There are a lot of runes which create cores; they all
+start with `|`, and are basically macros that turn into `|%`.)
+
+The payload of a core produced with `|%` is the subject with
+which `|%` is compiled. We might say that `|%` wraps a core
+around its subject. In this case, the subject of the `|%`,
+and thus payload, is our `arg=@ud` argument.
+
+Then we used this core as the subject of the simple wing `inc`.
+(Remember that `=<(a b)` is just `=>(b a)`.)
+
+We can actually print out a core. Take out the `=< inc`:
+```
+|%
+++ inc
+ +(arg)
+--
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+!!!
+
+~tasfyn-partyv:dojo/sandbox> ? +test 42
+!!!
+```
+Cores can be large and complex, and we obviously can't render all
+the data in them, either when printing a type or a value. At
+some point, you'll probably make the mistake of printing a big
+core, maybe even the whole kernel, as an untyped noun. Just
+press ^C.
+
+## Adding a counter
+
+To decrement, we need to count up to the argument. So we need a
+counter in our subject, because where else would it go? Let's
+change the subject to add a counter, `pre`:
+```
+=> [pre=0 .]
+=< inc
+|%
+++ inc
+ +(arg)
+--
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+43
+```
+Once again, `.` is the whole subject, so we're wrapping it in a
+cell whose head is `pre=0`. Through the magic of labels, this
+doesn't change the way we use `arg`, even though it's one level
+deeper in the subject tree. Let's look at the subject again:
+```
+=> [pre=0 .]
+.
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+[pre=0 arg=42]
+~tasfyn-partyv:dojo/sandbox> ? +test 42
+ [pre=@ud arg=@ud]
+[pre=0 arg=42]
+```
+There's actually a simpler way to write this. We've seen it
+already. It's not exactly a variable declaration:
+```
+=+ pre=0
+.
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+[pre=0 arg=42]
+```
+
+## We actually decrement
+
+Now we can write our actual decrement program:
+```
+=+ pre=0
+=< dec
+|%
+++ dec
+ ?: =(arg +(pre))
+ pre
+ dec(pre +(pre))
+--
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+41
+```
+`=(a b)` is an irregular form of `.=(a b)`, ie, "dottis" or the
+noun `[%dtts a b]`. Likewise, `+(a)` is `.+(a)`, ie, "dotlus"
+or `[%dtls a]`.
+
+`?:` is a regular rune which does exactly what you think it does.
+Bear in mind, though, that in Hoon 0 (`&`, "rob") is true and 1
+(`|`, "bar") is false.
+
+The real action is in `dec(pre +(pre))`. This is obviously an
+irregular form -- it's the same mutation form we saw before.
+Writing it out in full regular form:
+```
+=+ pre=0
+=< dec
+|%
+++ dec
+ ?: =(arg +(pre))
+ pre
+ %= dec
+ pre +(pre)
+ ==
+--
+~tasfyn-partyv:dojo/sandbox> +test 42
+41
+```
+`%=`, "centis", is the rune which almost every use of a wing
+resolves to. It might be called "evaluate with changes."
+
+When we evaluate with changes, we take a wing (`dec`) here and
+evaluate it as described above. Searching in the subject, which
+is of course our core, we find an arm called `dec` and run it.
+
+The changes (replacing `pre` with `+(pre)`) are always applied
+relative to the core we landed on (or the leg we landed on).
+The change wing is relative to this target; the subject of the
+replacement (`+(pre)`) is the original subject.
+
+So, in English, we compute the `dec` arm again, against a new
+core with a new payload that contains an incremented `pre`.
+And thus, we decrement. Doesn't seem so hard, does it?
diff --git a/pub/doc/hoon/tutorial/4-functions.md b/pub/doc/hoon/tutorial/4-functions.md
new file mode 100644
index 000000000..c8429e3d6
--- /dev/null
+++ b/pub/doc/hoon/tutorial/4-functions.md
@@ -0,0 +1,261 @@
+# Hoon 4: toward actual functions
+
+Okay, we've programmed. We've achieved decrement. We've written
+what is in some sense a loop. What next?
+
+Well... we're still feeling vaguely disappointed. Because we're
+supposed to be doing *functional programming*. And we haven't
+yet written any *functions*.
+
+After all, in Hoon we don't really write a command-line utility
+to decrement `42`. We write `(dec 42)`. You probably realize
+that on the inside, this is not the same thing as a function in a
+normal functional language. The Tasmanian tiger is not a tiger.
+On the other hand, it certainly *looks* like a function call.
+
+So how do we write the function?
+
+In this chapter, we'll modify `+test` to extend the subject so
+that we can write our result as `(dec arg)`. Or rather, `(duck
+arg)`, because we want to get out of training wheels and stop
+clearing the subject soon.
+
+## Form of the solution
+
+```
+=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
+ (duck arg)
+!! :: some interesting core
+```
+`!!`, or "zapzap" or `[%zpzp ~]`, can go anywhere a twig can and
+always crashes. Because its span is the empty set (`%void`), it
+doesn't cause type inference problems.
+
+In place of the `!!`, we'll put a core, effectively a library,
+that provides our new, improved decrement function `duck`. We'll
+then call it with the irregular form, `(duck arg)`, which looks
+like a function call but is in fact some mysterious macro.
+
+## Some interesting core
+
+Translated into imperative programming, what we did in chapter 3
+was more like computing a function of a global variable. Now,
+we have to actually pass an argument to a function.
+
+Here's our first try:
+```
+=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
+ =+ gat=duck
+ =<(run gat(sam arg))
+=> ~
+|%
+++ duck
+ =+ sam=0
+ =+ pre=0
+ |%
+ ++ run
+ ?: =(sam +(pre))
+ pre
+ run(pre +(pre))
+ --
+--
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+41
+```
+We step back and contemplate our handiwork. Is it good? Well...
+it works. Reading programs written without syntactic sugar is
+about as fun as eating raw chocolate nibs.
+
+What did we do? In the `duck` arm (we often write `++duck`, for
+obvious reasons) we produce a core whose payload is `[pre=0 num=0
+~]`, and whose battery contains `++run`.
+
+In the result twig, we first use `++duck` to extend our subject
+with a core named `gat`. We then use `run` on that gate. Why do
+we need this `gat`? Why can't we just write `=<(run duck(sam
+arg))`?
+
+Because the arm is computed *after* the mutation. But here we
+need the mutated *result* of `++duck`. Instead, what this code
+is doing is trying to mutate `sam` within the core that contains
+`++duck`. Where it doesn't exist, so your code won't compile.
+
+And note that with `=<`, we've placed our library structurally
+between the original subject and the program we're writing,
+but lexically at the bottom with zero left margin. We also
+clear the subject to keep things simple.
+
+## A more regular structure
+
+It actually gets worse. To make this code look simpler, we need
+to make it more complex. While "function calls" actually fit
+quite well into the Hoon architecture, they're also a nontrivial
+synthetic construction. We'll build the desugared form the hard
+way, then show you where we put the sugar in.
+
+The desugared canonical decrement:
+```
+=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
+ =+ gat=duck
+ =<(run gat(sam arg))
+=> ~
+|%
+++ duck
+ =+ sam=0
+ |%
+ ++ run
+ =+ pre=0
+ =< loop
+ |%
+ ++ loop
+ ?: =(sam +(pre))
+ pre
+ loop(pre +(pre))
+ --
+ --
+--
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+41
+```
+Yuck. Okay, let's fix this.
+
+## Art of the loop
+
+First, look at our little `++loop`. It works just like our old
+`++run` loop. We notice that there's actually something nice
+about it: we don't use the symbol `loop` anywhere outside these 7
+lines of code. It's not exported at all.
+
+Actually, the symbol `loop` name is useless and redundant.
+Making up names is one of the hard problems in computer science,
+so why solve it? For just this reason, Hoon has an *empty name*,
+which as a constant is a zero-length symbol (`%$` instead of
+`%foo`), and as a limb is the `buc` symbol (`$`). With `$`,
+our loop becomes:
+```
+=< $
+|%
+++ $
+ ?: =(sam +(pre))
+ pre
+ $(sam +(run))
+--
+```
+This may not seem like a huge improvement. It's not. But it's
+exactly equivalent to the synthetic rune `|-`, "bardas":
+```
+|- ?: =(sam +(pre))
+ pre
+ $(pre +(pre))
+```
+This is obviously the canonical Hoon loop. It leaves us with
+```
+=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
+ =+ gat=duck
+ =<(run gat(sam arg))
+=> ~
+|%
+++ duck
+ =+ sam=0
+ |%
+ ++ run
+ =+ pre=0
+ |- ?: =(sam +(pre))
+ pre
+ $(pre +(pre))
+ --
+--
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+41
+```
+
+## Is this a lambda?
+
+Could we use `$` for `++run`? It certainly sounds like the same
+kind of thing as `++loop` -- just a word we invented to mean "do
+it." Should the programmer have to invent these kinds of words?
+```
+=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
+ =+ gat=duck
+ =<($ gat(sam arg))
+=> ~
+|%
+++ duck
+ =| sam=@ud
+ |%
+ =+ pre=0
+ ++ $
+ |- ?: =(sam +(pre))
+ pre
+ $(pre +(pre))
+ --
+--
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+41
+```
+(Besides `run` to `$`, we changed `=+ sam=0` to `=| sam=@ud`.
+Let's just remember that there's some magic here. We'll come
+back and explain it later.)
+
+This is still kind of ugly -- but it's exactly equivalent to
+```
+=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
+ =+ gat=duck
+ =<($ gat(sam arg))
+=> ~
+|%
+++ duck
+ |= sam=@ud
+ =+ pre=0
+ |- ?: =(sam +(pre))
+ pre
+ $(pre +(pre))
+--
+
+~tasfyn-partyv:dojo/sandbox> +test 42
+41
+```
+Doesn't that look like a function? Indeed, we're done with
+`++duck` -- that's what a Hoon decrement should look like.
+If you squint a little, `|=` ("bartis") might even be a strange,
+deformed lambda rune.
+
+Since it's doing something simple, we might well even compress
+the whole body of the function into one wide-form line:
+```
+=+(pre=0 |-(?:(=(sam +(pre)) pre $(pre +(pre)))))
+```
+(According, of course, to taste -- this is a bit tight for some.)
+
+## Gates and how to call them
+
+Our call site remains a disaster, though. We'll need moar sugar.
+
+But first, let's look at this lambda-thing we've made. What is
+the noun produced by `++duck`? Our term for it is a "gate," but
+nobody will hate you for saying "function." And while we "slam"
+our gates, you can feel free to just "call" them.
+
+A gate is a core, of course, but a special kind of core. All
+cores are shaped like `[battery payload]`. A gate is shaped like
+`[formula [sample context]]`. A gate has one arm, `$`, so its
+battery is just a formula. To slam a gate, you replace its
+sample (`+6` or `+<`, "luslit" or "lust") with your own noun,
+and apply the formula to the mutated gate.
+
+As we explained earlier, `duck(sam arg)` is not the right way to
+mutate the gate we make with `duck`, because it's actually
+trying to mutate the core we used to make `duck`. But there has
+to be some sugar to do this, and there is: `%*`, "centar". We
+can replace our call site with `%*($ duck sam arg)`.
+
+This is also not quite orthodox, because the whole point of a
+gate is the canonical shape that defines a calling convention.
+We can and should say: `%*($ duck +< arg)`.
+
+Unsurprisingly, this in turn is `%-(duck arg)` in regular form,
+or `(duck arg)`
diff --git a/pub/doc/reference.md b/pub/doc/interpreter.mdy
similarity index 63%
rename from pub/doc/reference.md
rename to pub/doc/interpreter.mdy
index 5e85776d8..4c0f3d951 100644
--- a/pub/doc/reference.md
+++ b/pub/doc/interpreter.mdy
@@ -1,9 +1,13 @@
+---
+sort: 3
+---
+
-References
+Interpreter
==========
-These references cover terminology and our interpreter, `vere`.
+The urbit interpreter and C code.
diff --git a/pub/doc/reference/glossary.md b/pub/doc/interpreter/glossary.md
similarity index 100%
rename from pub/doc/reference/glossary.md
rename to pub/doc/interpreter/glossary.md
diff --git a/pub/doc/reference/u3.md b/pub/doc/interpreter/u3.md
similarity index 100%
rename from pub/doc/reference/u3.md
rename to pub/doc/interpreter/u3.md
diff --git a/pub/doc/reference/vere.md b/pub/doc/interpreter/vere.md
similarity index 100%
rename from pub/doc/reference/vere.md
rename to pub/doc/interpreter/vere.md
diff --git a/pub/doc/nock.md b/pub/doc/nock.mdy
similarity index 98%
rename from pub/doc/nock.md
rename to pub/doc/nock.mdy
index aa9a8f897..c477a997f 100644
--- a/pub/doc/nock.md
+++ b/pub/doc/nock.mdy
@@ -1,3 +1,7 @@
+---
+sort: 0
+---
+
nock
diff --git a/pub/doc/talk.md b/pub/doc/talk.md
deleted file mode 100644
index b2ac5e66b..000000000
--- a/pub/doc/talk.md
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-talk
-====
-
-talk is our messaging application.
-
-talk is in dire need of better documentation
-
-
-
-------------------------------------------------------------------------
-
-This document should include
the command reference somehow.
diff --git a/pub/doc/talk/help.txt b/pub/doc/talk/help.txt
deleted file mode 100644
index eaf20e62a..000000000
--- a/pub/doc/talk/help.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-Besides `;help`, there are four main `talk` commands:
-
- ;join ~urbit-name/channel
-
-`;join` subscribes your main feed to a remote channel.
-
- ;create channel %name 'description'
-
-`;create` creates a channel on your urbit.
-
- ;
-
-`;` activates a previous message number, like a URL that got
-clipped.
-
- ;
-
-`;` sets the target for your messages, such as `;~urbit-name`
-for a private message, or `;/channel`
-
- ;
-
-By itself is "autotarget", and maintains the audience of the last message
-heard.
diff --git a/pub/doc/tools.mdy b/pub/doc/tools.mdy
new file mode 100644
index 000000000..a1b0b7caf
--- /dev/null
+++ b/pub/doc/tools.mdy
@@ -0,0 +1,10 @@
+---
+sort: 4
+---
+
+tools
+====
+
+User-level tools and utilities.
+
+
diff --git a/pub/doc/tools/clay.md b/pub/doc/tools/clay.md
new file mode 100644
index 000000000..b48d94ad9
--- /dev/null
+++ b/pub/doc/tools/clay.md
@@ -0,0 +1,207 @@
+`%clay`
+========
+
+## Paths
+
+### Structure
+
+Urbit paths have a very specific structure. First, since the clay
+filesystem has a global namespace, the first element in any path
+is the particular urbit whose filesystem you are trying to
+access.
+
+The second element specifies which desk you wish to access on
+that urbit. Desks are independent branches (in the
+revision-control sense) of their filesystem.
+
+The third element specifies the revision number for that
+desk. The remainder of the path is the path to the file.
+
+Thus, a path in clay is:
+
+`/urbit/desk/revision/path`.
+
+For example, to get revision 5 of `/try/readme/md` off the `home`
+desk on `~sampel-sipnym`, use:
+
+`/~sampel-sipnym/home/5/try/readme/md`.
+
+### Shortcuts
+
+`%` refers to the current working
+directory. `%%` refers to our parent, `%%%` refers to our
+grandparent, and so forth.
+
+For example:
+
+ XX TBD
+
+
+From the other direction, inserting a `=` into a path copies the
+corresponding element from the current path into the path that
+you're trying to access.
+
+For example, if the current path is referencing our ship at the
+current time, to reference `/try/readme`, use:
+
+`/===try/readme`.
+
+
+### Accessing commits
+
+There are three ways to refer to particular commits in the
+revision history. First, one can use the revision number.
+Second, one can use any absolute time between the one numbered
+commit and the next (inclusive of the first, exclusive of the
+second). Thirdly, every desk has a map of labels to revision
+numbers. These labels may be used to refer to specific commits.
+
+
+## `ls`
+
+`+ls /path` gives a directory listing at a path
+
+## `cat`
+
+`+cat /path`
+prints out the file at the given path.
+
+## `mount`
+
+It's often useful to "mount" the clay filesystem to unix, so that
+you can interact with it with the traditional unix tools. The
+syntax to do this is as follows:
+
+ |mount /path [%mount-point]
+
+This mirrors the desk out to unix in at the path
+` `. If you don't supply a
+`%mount-point`, we use the last element in the path. Thus, if
+you mount `%/pub/doc`, it'll by default put it in `doc`.
+
+*The mount point is monitored Dropbox-style, so every change you
+make to the file in unix is automatically commited to clay.*
+
+You can unmount by specifying either the path or the mount point.
+
+ |unmount /path
+ |unmount %mount-point
+
+## `merge`
+
+Often, it's useful to be able to merge a desk into another desk.
+The other desk does not, of course, need to be on the same urbit:
+for example, the standard way to distribute an app is to put it
+on a desk and let other people merge it into their own urbit.
+
+The syntax is as follows:
+
+ |merge %to-desk ~from-urbit %from-desk [%strategy]
+
+There are seven different merge strategies. Throughout our
+discussion, we'll say that the merge is from Alice's desk to
+Bob's.
+
+### Native strategies
+
+A `%init` merge should be used iff it's the first commit to a
+desk. The head of Alice's desk is used as the number 1 commit to
+Bob's desk. Obviously, the ancestry remains intact when
+traversing the parentage of the commit, even though previous
+commits are not numbered for Bob's desk.
+
+A `%this` merge means to keep what's in Bob's desk, but join the
+ancestry. Thus, the new commit has the head of each desk as
+parents, but the data is exactly what's in Bob's desk. For those
+following along in git, this is the 'ours' merge strategy, not
+the '--ours' option to the 'recursive' merge strategy. In other
+words, even if Alice makes a change that does not conflict with
+Bob, we throw it away.
+
+A `%that` merge means to take what's in Alice's desk, but join
+the ancestry. This is the reverse of `%this`.
+
+A `%fine` merge is a "fast-forward" merge. This succeeds iff one
+head is in the ancestry of the other. In this case, we use the
+descendant as our new head.
+
+For `%meet`, `%mate`, and `%meld` merges, we first find the most
+recent common ancestor to use as our merge base. If we have no
+common ancestors, then we fail. If we have multiple most
+recent common ancestors, then we have a criss-cross situation,
+which should be handled delicately. At present, we don't handle
+this kind of situation, but something akin to git's 'recursive'
+strategy should be implemented in the future.
+
+There's a functional inclusion ordering on `%fine`, `%meet`,
+`%mate`, and `%meld` such that if an earlier strategy would have
+succeeded, then every later strategy will produce the same
+result. Put another way, every earlier strategy is the same as
+every later strategy except with a restricted domain.
+
+A `%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.
+
+A `%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 files.
+
+A `%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.
+
+### Metastrategies
+
+There's also a meta-strategy `%auto`, which is the most common.
+If no strategy is supplied, then `%auto` is assumed. `%auto`
+checks to see if Bob's desk exists, and if it doesn't we use a
+`%init` merge. Otherwise, we progressively try `%fine`,
+`%meet`, and `%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. For each file in the produced set of
+conflicting files, we call the `++mash` function for the
+appropriate mark, which annotates the conflicts if we know how.
+
+Finally, we display a message to the user informing them of the
+scratch desk's existence, which files have annotated conflicts,
+and which files have unannotated conflicts. When the user has
+resolved the conflicts, they can merge the scratch desk back into
+Bob's desk. This will be a `%fine` merge since Bob's head is in
+the ancestry of the scratch desk.
+
+## Autosync
+
+Since clay is reactive, it's possible for changes to the
+filesystem to cause various actions. An important use of this is
+in enabling "autosync". When a desk is synced to another, any
+changes to the first desk are automatically applied to the
+second.
+
+This isn't simply mirroring, since the local desk might have
+changes of its own. We use the full merge capabilities of clay
+to try to make the merge clean. If there are conflicts, it'll
+notify you and let you resolve them.
+
+There can be complex sync flows, some of which are useful.
+Often, many urbits will be synced to some upstream desk that is
+trusted to provide updates. Sometimes, it's useful to sync two
+desks to each other, so that changes to one or the other are
+mirrored.
+
+The syntax for syncing and unsyncing desks is as follows:
+
+ |sync %to-desk ~from-urbit %from-desk
+ |unsync %to-desk ~from-urbit %from-desk
\ No newline at end of file
diff --git a/pub/doc/tools/dojo.md b/pub/doc/tools/dojo.md
new file mode 100644
index 000000000..c273c78ba
--- /dev/null
+++ b/pub/doc/tools/dojo.md
@@ -0,0 +1,548 @@
+
+# `:dojo`
+
+The dojo is a typed functional shell. Its prompt is:
+
+ ~urbit-name:dojo>
+
+
+### Quickstart
+
+To print a Hoon expression or other recipe:
+
+ ~urbit-name:dojo> (add 2 2)
+
+To save a recipe as a variable `foo`:
+
+ ~urbit-name:dojo> =foo (add 2 2)
+
+To save as a unix file (`$pier/.urb/put/foo/bar.baz`):
+
+ ~urbit-name:dojo> .foo/bar/baz (add 2 2)
+
+To save as an urbit file (`/===/foo/bar/baz`):
+
+ ~urbit-name:dojo> *foo/bar/baz (add 2 2)
+
+A noun generator with ordered and named arguments:
+
+ ~urbit-name:dojo> +make one two three, =foo (add 2 2), =bar 42
+
+A poke message to an urbit daemon:
+
+ ~urbit-name:dojo> :~urbit-name/talk (add 2 2)
+
+A system command to `:hood`:
+
+ ~urbit-name:dojo> |reload %vane
+
+### Manual
+
+An Urbit value is called a "noun." A noun is either an unsigned
+integer ("atom") or an ordered pair of nouns ("cell"). Nouns
+are just values, with no cyclic structure or pointer identity.
+
+The dojo is your safe space for hand-to-hand combat with nouns.
+Every dojo command builds a "product" noun functionally, then
+applies this product in a side effect -- show, save, or send.
+
+#### Theory
+
+The dojo is not just a Hoon interpreter. Hoon is a purely
+functional language; dojo recipes are *conceptually* functional,
+but they often use concrete actions or interactions. A simple
+Hoon expression is only one kind of recipe.
+
+A recipe can get data from an HTTP GET request or an interactive
+input dialog. It can also query, even block on, the Urbit
+namespace. These operations are *conceptually* functional, but
+not *actually* functional. They don't belong in a pure Hoon
+expression, but they do belong in a dojo recipe. A recipe is "FP
+in the large," more like Unix pipes than Haskell monads.
+
+The dojo is "single-threaded" in each session. One session can
+work on one command at a time. The session does not accept user
+input while processing a command, even when it blocks over the
+network. And each session's state is independent. (If you want
+to work on two things at a time, connect two console sessions to
+your dojo.)
+
+Once you've built your product noun, you show, save, or send it.
+
+You can pretty-print the product to the console. You can save it
+-- as a dojo variable, as a revision to the Urbit filesystem, or
+as an export to a file in the Unix filesystem. Or you can
+send it -- staying native with an Urbit poke, or going retro
+with an HTTP PUT/POST.
+
+All these operations are typed. Hoon is a statically typed
+language, but the dojo is a dynamic interpreter. The nouns you
+build in the dojo are dynamically typed nouns, or "cages".
+
+A cage actually has two layers of type: "mark," a network label
+(like a MIME type), and "range," a Hoon language type. When a
+cage is sent across the Urbit network, the receiving daemon
+validates the noun against its own version of the mark, and
+regenerates the range.
+
+Of course, sometimes a recipe produces a noun with mark `%noun`,
+meaning "any noun," and range `*`, the set of all nouns. We have
+no choice but to do the best we can with mystery nouns, but we
+prefer a formal description.
+
+Marks let us perform a variety of formal typed operations on
+nouns: validation of untrusted data, format conversion, even
+patch and diff for revision control.
+
+#### Other resources
+
+An excellent way to understand `:dojo` is to read the source,
+which is in `/===/ape/dojo/hoon`.
+
+Unfortunately, you may or may not know Hoon. We'll use some Hoon
+snippets here for defining structures and grammars. Just think
+of it as pseudocode -- the meaning should be clear from context.
+
+#### Syntax and semantics
+
+To use the dojo, type a complete command at the dojo prompt.
+The simplest command just prints a Hoon expression:
+
+ ~urbit-name:dojo> (add 2 2)
+
+Hit return. You'll see:
+
+ > (add 2 2)
+ 4
+ ~urbit-name:dojo>
+
+Similarly in tall form,
+
+ ~urbit-name:dojo> %+ add 2 2
+ > %+ add 2 2
+ 4
+ ~urbit-name:dojo>
+
+An incomplete command goes into a multiline input buffer. Use
+the up-arrow (see the console history section) to get the last
+command back, edit it so it's just `%+ add 2`, and press return.
+You'll see:
+
+ > %+ add 2
+ ~urbit-name/dojo<
+
+Enter `2`. You'll see:
+
+ > %+ add 2
+ 2
+ 4
+ ~urbit-name/dojo>
+
+The full command that parses and runs is the concatenation of all
+the partial lines, with a space inserted between them. To clear
+all multiline input, just hit return on an empty prompt.
+
+##### Command structure
+
+Every finished line is parsed into one `++dojo-command`:
+
+ ++ dojo-command ::
+ $% [%edit p=path q=dojo-recipe] :: modify clay file
+ [%http p=? q=purl r=dojo-recipe] :: http post or put
+ [%poke p=goal q=dojo-recipe] :: send request
+ [%save p=path q=dojo-recipe] :: replace clay file
+ [%show p=dojo-recipe] :: print to console
+ [%unix p=path q=dojo-recipe] :: export to unix
+ [%verb p=term q=dojo-recipe] :: store variable
+ == ::
+
+Each kind of `++dojo-command` is an action that depends on one
+noun thproduction, a `++dojo-recipe`. We describe first the
+commands, then the recipes.
+
+---
+
+###### `[%show p=dojo-recipe]`
+
+To print the product, the command is just the recipe:
+
+ ~urbit-name:dojo> (add 2 2)
+
+---
+
+###### `[%verb p=term q=dojo-recipe]`
+
+To save the product to a variable `foo`:
+
+ ~urbit-name:dojo> =foo (add 2 2)
+
+`foo` goes into your Hoon subject (scope) and is available to all
+expressions.
+
+To unbind `foo`:
+
+ ~urbit-name:dojo> =foo
+
+The dojo has a set of special variables, some read-write and some
+read-only: `dir`, `lib`, `arc`, `now`, `our`.
+
+The read-write specials are `dir`, `lib` and `arc`. `dir` is the beak
+(revision-control branch) and directory this session is operating in,
+and normally accessed/set with `%`. `lib` is a set of libraries, and
+`arc` a set of structures, to put in the Hoon subject.
+
+Read-only specials are `now`, the current (128-bit `@da`) time,
+and `our`, the current urbit.
+
+---
+
+###### `[%edit p=path q=dojo-recipe]`
+###### `[%save p=path q=dojo-recipe]`
+
+The product is either a new version of, or a modification to,
+the Urbit file at the given path. (See the discussion of Urbit
+filesystem paths.)
+
+To save:
+
+ ~urbit-name:dojo> *%/numbers/four (add 2 2)
+
+To edit:
+
+ ~urbit-name:dojo> -%/numbers/four (add 2 2)
+
+A save (`*`) overwrites the current (if any) version of the file
+with a new version of any mark. The save command above will work
+(if you want `/numbers/four` at your current path).
+
+An edit (`-`) produces a diff whose mark has to match the diff
+mark for the current version of the file. The edit command above
+will not work, because evaluating a Hoon expression like `(add 2
+2)` just produces a `%noun` mark, ie, an arbitrary noun.
+
+For either saves or edits, the current version of the file must
+be the same version specified in the write -- in other words,
+we can only write to HEAD. If someone else has sneaked in a
+change since the version specified, the command will fail.
+
+---
+
+###### `[%unix p=path q=dojo-recipe]`
+
+ ~urbit-name:dojo> ./numbers/four (add 2 2)
+
+The product is saved as a Unix file (its mark is translated
+to MIME, and the MIME type is mapped as the extension).
+
+---
+
+###### `[%poke p=goal q=dojo-recipe]`
+
+A poke is a one-way transactional request. It either succeeds
+and returns no information, or fails and produces an error dump.
+
+Every poke is sent to one daemon on one urbit. The default urbit
+is your urbit. The default daemon is the system daemon, `:hood`.
+The following syntactic forms are equivalent:
+
+ ~urbit-name:dojo> :~urbit-name/hood (add 2 2)
+ ~urbit-name:dojo> :hood (add 2 2)
+ ~urbit-name:dojo> :~urbit-name (add 2 2)
+ ~urbit-name:dojo> : (add 2 2)
+
+Urbit pokes do not have a separate verb. The mark of the message
+defines the semantics of the operation. You don't call a method
+`foo` whose argument is a noun in mark `bar` -- you poke a noun
+in mark `bar`. The mark is the protocol is the method.
+
+If the poke succeeds, you'll see an `>=` line. If not, you'll
+see an error report, typically with a stack trace.
+
+It's common (but not necessary) to use a custom generator for the
+daemon you're talking to. (For generators, see below.) Hence
+
+ ~urbit-name:dojo> :~urbit-name/fish +fish/catch (add 2 2)
+
+It's irritating to type "fish" twice, just because we're using a
+fish generator to talk to a fish daemon. Hence a shortcut:
+
+ ~urbit-name:dojo> :~urbit-name/fish|catch (add 2 2)
+
+If we combine all these defaults, we get the "system command"
+shortcut:
+
+ ~urbit-name:dojo> :~urbit-name/hood +hood/reload %ames
+ ~urbit-name:dojo> |reload %ames
+
+This is the most common poke, a generated message to your own
+hood.
+
+---
+
+##### `[%http p=? q=purl r=dojo-recipe]`
+
+The Web has its own poke, unfortunately in two flavors. To POST,
+
+ ~urbit-name:dojo> +http://website.com (add 2 2)
+
+To PUT:
+
+ ~urbit-name:dojo> -http://website.com (add 2 2)
+
+As with a poke, you'll get a >= for success, or an error report.
+
+---
+
+##### Recipes, models and filters
+
+But wait, what's a recipe? Simplifying the actual code slightly:
+
+ ++ dojo-recipe :: functional build
+ $% [%ex p=twig] :: hoon expression
+ [%as p=mark q=dojo-recipe] :: conversion
+ [%do p=twig q=dojo-recipe] :: apply gate
+ [%ge p=dojo-script] :: generator
+ [%ur p=purl] :: get url
+ [%tu p=(list dojo-recipe)] :: tuple
+ == ::
+ ++ dojo-script :: script
+ $: p=path :: core recipe
+ q=dojo-config :: configuration
+ == ::
+ ++ dojo-config :: configuration
+ $: p=(list dojo-recipe) :: by order
+ q=(map term (unit dojo-recipe)) :: by keyword
+ == ::
+
+---
+
+###### `[%ex p=twig]`
+
+The twig in an `%ex` recipe is a Hoon expression. The recipe
+syntax is just the Hoon syntax.
+
+The subject of the twig is a core stack: first the Hoon kernel,
+then the Arvo standard library, then the structures and libraries
+in `lib` and `arc`. On the very top are the dojo variables.
+
+A twig produces the trivial mark `%noun`, except in two cases
+where the dojo can do better. The dojo analyzes the twig to
+detect two trivial cases where direct evaluation gives us a mark:
+a variable reference like `foo` that matches a dojo variable, or
+an urbitspace dereference like `.^(/cx/~urbit-name/main/1/foo)`.
+
+---
+
+###### `[%tu p=(list dojo-recipe)]`
+
+A is just a tuple of recipes, using the normal Hoon syntax for
+a tuple. `[a]` is `a`, `[a b]` the cell `[a b]`, `[a b c]` the
+cell `[a [b c]]`.
+
+A tuple, unless it's a trivial 1-tuple, is always marked `%noun`.
+
+---
+
+###### `[%ge p=dojo-script]`
+
+A `%ge` is a generator, a configurable script loaded from the
+filesystem.
+
+The script recipe `++dojo-script` specifies a script path, a list
+of ordered arguments, and a list of keyword arguments. All the
+arguments are recipes. The path specifies a Hoon source file in
+`/===/gen/[path]`.
+
+For the path `/fun/make`, the ordered arguments `1`, `2` and `3`,
+and the named arguments `foo` and `bar`, the syntax is:
+
+ ~urbit-name:dojo> +fun/make 1 2 3, =foo (add 2 2), =bar 42
+
+Unless this non-closed form is the end of a command, it needs to
+be surrounded by `[]` to make it play well with others.
+
+Generator programming is covered in the dojo developer's guide.
+The user doesn't need to know or notice how the generator gets
+its input (if any), except in one case: a dialog.
+
+A dialog generator will take over the prompt and ask you
+questions. If this seems terrifying, ^D will abort the dialog,
+the recipe, and the command, and take you back to the dojo.
+
+---
+
+###### `[%as p=mark q=dojo-recipe]`
+
+`%as` is a mark conversion. Since the input to it is another
+recipe, we can chain them to make a conversion pipeline.
+
+To convert a recipe, just precede it with the converison form, `&mark`:
+
+ ~urbit-name:dojo> &noun (add 2 2)
+ ~urbit-name:dojo> &md (add 50 7)
+
+---
+
+###### `[%do p=twig q=dojo-recipe]`
+
+`%do` is a Hoon functino (gate) application. It can also be in a pipeline.
+
+Its syntax is a hoon expression preceeded by `_`:
+
+ ~urbit-name:dojo> _lore 'hello\0aworld'
+ ~urbit-name:dojo> _|=(a=@ (mul 3 a))} (add 2 2)
+
+---
+
+###### `[%ur p=purl]`
+
+A simple HTTP get produces the result as a `%httr` noun.
+
+---
+
+### Development
+
+Developing dojo generators is the easiest form of Hoon programming.
+Generator scripts are found in the `gen` folder.
+
+#### Configuration
+
+All generator scripts are configured with the same configuration gate:
+
+ |= $: [now=@da eny=@ bec=beak]
+ [arg=my-arguments opt=my-options]
+ ==
+
+We try to minimize boilerplate, but you can't get out of this
+one. The dojo will slam this configuration gate to create your
+generator.
+
+The head of the sample is a system context. `now` is the date of
+the call; `eny` is 256 bits of entropy; `bec` is a triple
+`[p=ship q=desk r=case]` (ie, the root of a filesystem path).
+This beak is the path to the script, not the current path within
+the dojo (dojo variables are not, unlike in Unix, visible to
+generator scripts).
+
+`arg` and `opt` are whatever you want them to be. (Use `~` if
+you have no arguments or options.) The dojo will replace `arg`
+with the user's ordered arguments, and replace any options in
+`opt` specified by the user's named arguments. (More exactly,
+if the user specifies `=foo 42`, your `opt` is replaced with
+`opt(foo 42)`.)
+
+Bear in mind that dojo syntax is list-centric, so your `arg` will
+always end with a `~`. For instance,
+
+ ~urbit-name/dojo> +fun/make 1 2 3
+
+will generate an `arg` of `[1 2 3 ~]`. Yes, this is the only
+place in Urbit where we do list-centric arguments.
+
+Note also that script configuration is typed. The user's command
+will fail if there's a type mismatch. But `arg` does not have to
+be a homogeneous list -- just a tuple with `~` on the end. Also,
+you can use `arg=*` and sort out the nouns by hand.
+
+You can also use `*` anywhere if you're not interested in the
+system context, or in
+
+#### Generators
+
+There are three kinds of generators: builders (with no special
+I/O), dialogs (which read console input), and scrapers (which
+pull data from the webs). Any generator can use `.^` to both
+read from and block (wait for remote or delayed results) on
+the Urbit global namespace.
+
+A generator produces a cell whose tail is the configuration gate,
+and whose head is either `%say` for a builder, `%ask` for a
+dialog, or `%get` for a scraper.
+
+(If you want to write one generator which both prompts the user
+and scrapes the web, don't. Write two, and configure the second
+with the result of the first. We pay a price for keeping things
+stupid.)
+
+##### Builders
+
+A builder just produces a cask (mark-value cell) directly from
+the configuration gate. Here's the simplest builder, with a
+blank configuration:
+
+ :- %say |= *
+ :- %noun
+ "hello, world."
+
+##### Dialogs
+
+A dialog is a console input form. We recommend using the helpful
+`sole` structures, with
+
+ /- *sole
+
+(If you're interested in building your own dialogs without `sole`
+(not that complicated at all), it's easiest to start by
+reverse-engineering `sole`.)
+
+Otherwise, a dialog boilerplate (with blank configuration), which
+generates a `my-result` result with mark `%my-result-mark`:
+
+ :- %ask |= *
+ ^- (sole-result (cask my-result))
+ %+ sole-so %my-result-mark
+ *my-result
+
+Internally, a `++sole-result` is either a final result or a new
+dialog core with a new prompt. The dojo keeps running the dialog
+until it produces a final result.
+
+A dialog step can do one of three things: print a message, prompt
+for a value, or finish with a result. These are done with
+`sole-yo`, `sole-lo`, and `sole-so` respectively. Here's a
+simple dialog which uses all of them:
+
+ :- %ask |= *
+ ^- (sole-result (cask ,@ud))
+ %+ sole-yo leaf/"let's multiply two numbers..."
+ %+ sole-lo [%& %number "number one: "]
+ %+ sole-go dim:ag
+ |= one=@ud
+ %+ sole-lo [%& %number "number two: "]
+ %+ sole-go dim:ag
+ |= two=@ud
+ %+ sole-so %noun
+ (mul one two)
+
+`++sole-yo` prints a tank (prettyprint structure). See `++tank`
+in hoon.hoon.
+
+`++sole-lo` takes a prompt and a new dialog. In the example,
+`[%& %number "your number: "]` is a `++sole-prompt`. `&` as
+opposed to `|` means input is echoed (not a password).
+`%number` is a history label; all inputs with the same label
+share the same history buffer.
+
+The `++sole-dialog` is generally built with `++sole-go`, as used
+above. This takes a parsing `++rule` (here `dim:ag`, which
+parses a decimal), and a gate whose sample is the parsed value,
+producing a new dialog.
+
+##### Scrapers
+
+Most stuff on the internets is crap, but there's exceptions.
+Sometimes it's nice to get it and compute functions on it.
+
+A scraper is much like a dialog, except instead of `sole-lo` and
+`sole-go` it uses `sole-at`.
+
+ :- %get |= *
+ %+ sole-yo leaf/"Fetching example.com"
+ %+ sole-at [[& ~ `/com/example] `/ ~]
+ |= hit=httr
+ %+ sole-yo leaf/"Fetched."
+ %+ sole-so %httr
+ hit
+
+`++sole-at` takes a `purl` request url, and a gate through
+which to slam the result `httr`.
diff --git a/pub/doc/tools/talk.md b/pub/doc/tools/talk.md
new file mode 100644
index 000000000..04656e1a7
--- /dev/null
+++ b/pub/doc/tools/talk.md
@@ -0,0 +1,287 @@
+# `:talk`
+
+`:talk` is the Urbit appliance for chatter and notifications.
+For less sophisticated users, Urbit *is* just `:talk`. If you
+see `:talk` as "like Slack, but distributed," or "like IRC, but
+persistent and encrypted," you're not completely wrong.
+
+`:talk` is an unusual messenger in two ways. One: by default, it
+multiplexes all content streams into a single flow. Most UI
+researchers agree that context-switching is cognitively expensive
+and leads to surfing the Internet. (`:talk` is also used for
+your system notifications.)
+
+Two: text lines are limited to 64 ASCII bytes, no uppercase.
+This restriction is mobile-friendly and reduces the aesthetic
+impact of low-quality content.
+
+Messages in `:talk` are called "posts". Posts go to "stations,"
+which are just like IRC or Slack channels. Any urbit can host or
+subscribe to any number of stations.
+
+`:talk` is not a text-only messenger; it's designed to support
+arbitrary content in posts, from URLs to images to long-form
+text. (Only URLs right now.) However, any message on `:talk`
+has to be able to summarize itself in a 64-byte text line.
+
+There are four kinds of station: a write-only "mailbox" for
+direct messages, an invite-only "party" for private conversation,
+a read-only "journal" for curated content, and a public-access
+"board" for general use or abuse.
+
+While there's obviously no central `:talk` server for all of
+Urbit, and thus no such thing as a truly global station space,
+active Urbit stars cooperate to federate, manage and mirror a
+collectively-managed namespace, very like Usenet. These
+"federal" stations are generally public-access boards.
+
+### Quickstart
+
+Let's post something! At the default `:talk` prompt
+```
+~tasfyn-partyv:talk:
+```
+type the message:
+```
+~tasfyn-partyv:talk: hello, world.
+```
+And hit return. Don't worry, no one but you will see this. The
+`:` means you're posting to yourself. You'll get the post:
+```
+~tasfyn-partyv: hello, world.
+~tasfyn-partyv:talk:
+```
+It's boring to post to yourself. Let's join a station:
+```
+~tasfyn-partyv: ;join /urbit-test
+```
+(`/urbit-test` is a federal station, meaning it's hosted by your
+star (for `~tasfyn-partyv`, `~doznec`). The `/` notation is just
+an abbreviation for `~doznec/urbit-test`.)
+
+You'll see:
+```
+---------:talk| %porch subscribed to /urbit-test, called `>`
+---------:talk| rules of /urbit-test:
+---------:talk| test posts only. no shitposting. no pedos/nazis.
+ ~doznec> ~tasfyn-partyv admitted to %urbit-test
+~tasfyn-partyv:talk>
+```
+Notice the character assignment - stations you're subscribed to are
+assigned [consistent ASCII glyphs](#-station-glyphs), which you'll
+see in the log when you hear from these stations, and on the prompt
+when you're talking to them.
+
+Post a line to `/urbit-test`:
+```
+~tasfyn-partyv:talk> hello, world
+```
+You'll see, echoed back at you through `~doznec`:
+```
+~tasfyn-partyv:talk> hello, world
+```
+And of course, anyone else in `/urbit-test` will see it as well.
+But you don't care about `/urbit-test`, so leave it:
+```
+~tasfyn-partyv:talk> ;leave
+```
+You'll see:
+```
+---------:talk| %porch has left /urbit-test, called `>`
+```
+Everyone else will see:
+```
+ ~doznec> ~tasfyn-partyv has left %urbit-test
+```
+
+Now you're ready to use `:talk` for real! List the federal
+groups currently available with
+```
+~tasfyn-partyv:talk> ;list
+```
+For general discussion about Urbit, we recommend `/urbit-meta`.
+
+### Basic usage
+
+#### Input conventions
+
+There are three kinds of inputs you can type at the `:talk`
+prompt: lines, URLs, and commands.
+
+A line is 64 bytes of ASCII lowercase and spaces. If the line
+starts with '@', it's an action (IRC `/me`).
+
+The `:talk` interface will let you keep typing past 64 bytes, but
+insert a Unicode bullet-point character in an appropriate space
+in your post, to show you the prospective linebreak. Your essay
+will be posted in multiple lines.
+
+A URL is any valid URL. A command is any line starting with `;`.
+
+#### Source annotation
+
+Any post in your flow is shown with its author, together with a
+glyph that shows how the post reached you. A post can reach you
+in one of three ways:
+
+Any post you see reached you in one of three ways. Either it was
+sent directly to just you; to you and others; or to a station you
+subscribe to.
+
+Posts to just you are `:`. Posts to you and others (a multiparty
+conversation) are `*`, unless you've bound this conversation to a
+glyph. Posts to a station use that station's glyph.
+
+You can see a list of glyph bindings with `;what`. Write
+`;what >` to see what station `>` is bound to, or
+`;what /urbit-test` to see if `/urbit-test` has a binding.
+
+#### Audience selection
+
+Audience selection is important in a multiplexed communicator!
+The audience is always shown in your prompt. If there's a glyph
+for it, it's shown as the glyph:
+```
+~tasfyn-partyv:talk>
+```
+Otherwise, the audience is shown in parens:
+```
+~tasfyn-partyv:talk(~wictuc-folrex)
+```
+
+`:talk` works fairly hard to get the audience right and minimize
+manual switching. But to manually set the audience, the command
+is simply `;station` - eg, `;~wictuc-folrex` for a direct post;
+`/urbit-test` or `~doznec/urbit-test` to post to a federal
+station, `%mystation` to post to a station on your own ship.
+For a station bound to a glyph, `;` then the glyph; eg, `;>`.
+
+You can post a line and set the audience in one command, eg:
+```
+;~wictuc-folrex this is a private message
+```
+
+You can configure your audience in a number of ways, which are
+applied in priority order. From strongest to weakest:
+
+- if typing a post, the audience when you started typing.
+- if you activated a post (see below), the post you activated.
+- if you manually locked the audience (see above), that audience.
+- audience of the last post received.
+- audience of the last post sent.
+
+You can clear any audience setting layer by moving your cursor to
+the start of the line and pressing backspace (whether the line is
+empty or not). Posting a line clears the typing and activation
+configurations.
+
+#### Post activation and numbering
+
+Every post can summarize itself in 64 bytes. But some posts
+contain more information, which is not displayed by default.
+Displaying this "attachment" is an opt-in operation. In the
+post, it's marked by an underscore `_`, instead of a space,
+between source and content.
+
+The conventional example is a URL. When you post a URL:
+```
+~tasfyn-partyv:talk> http://foobar.com/moo/baz
+```
+This will appear in the flow as:
+```
+~tasfyn-partyv>_foobar.com
+```
+meaning that `~tasfyn-partyv` posted a link to `foobar.com`,
+on the station or conversation whose glyph is `>`.
+
+The effect of activating a post depends on the post. For a link,
+the full URL is shown and (system permitting) put into the OS's
+clipboard, or even automatically navigated to. Even for a text
+post, activating shows the full audience, for complex audiences.
+
+Posts in your `:talk` flow are numbered; the numbers are printed
+every five posts, as
+```
+----------[5955]
+```
+You can specify a post to activate in two ways: by absolute or
+relative position. Absolute position is a direct history number:
+```
+;5955
+```
+If you use fewer digits than are in the current flow number, the
+high digits are defaulted "deli style" - if the current number is
+5955, typing `;3` means `;5953`, and `;140` means `;5140`. To
+actually activate post `3`, write `;0003`.
+
+A unary sequence of `;` characters looks backward from the
+present. `;` activates the most recent post; `;;` the second
+most recent; etc.
+
+#### Nicknames
+
+Sometimes you know your Urbit friends by other names, on or
+offline. Use the `;nick` command to assign or look up
+nicknames.
+
+`;nick` with no arguments lists all nicknames; `;nick
+~tasfyn-partyv` looks up a nickname; `;nick curtis` searches in
+reverse; `;nick ~tasfyn-partyv curtis` creates a nickname.
+All nicknames must be 14 characters or less, lowercase.
+
+Of course, nicknames are strictly local - like the names on
+entries in a phonebook. Sometimes in a post you want to mention
+someone you know by a nickname. Just type `~curtis`, and `:talk`
+will replace it magically with `~tasfyn-partyv` (or beep if no
+`~curtis` is bound).
+
+#### Presence
+
+You'll see presence notifications when people enter or leave
+stations you're subscribed to.
+
+`;who` lists everyone in all your stations. `;who station`
+lists everyone in that station.
+
+#### Typing indicator
+
+If one or more urbits in your audience is typing, `:talk`'s
+presence system will detect it and change the prompt:
+```
+~tasfyn-partyv [~wictuc-folrex...]>
+```
+
+#### Creating and managing stations
+
+To create your own mailbox, party, journal or board:
+```
+;create party %myfunparty
+;create journal %serious-journal
+;create board %bizarre-board
+```
+etc.
+
+Every form of station has an exception list; to block
+`~wictuc-folrex` from your default mailbox `%porch`,
+```
+;block %porch ~wictuc-folrex
+```
+To invite people to `%myfunparty`:
+```
+;invite %myfunparty ~wictuc-folrex, ~sondel-forsut
+```
+To ban from `%bizarre-board`:
+```
+;banish %bizarre-board ~wictuc-folrex
+```
+To appoint a coauthor of `%serious-journal`:
+```
+;author %serious-journal ~sondel-forsut
+```
+
+#### Station Glyphs
+
+Station are assigned out of the list `:|}>`, then
+randomly out of it and the sets `-+*.`, ``,=`'^\/``,
+`$%&@`, and `{<[]()`, in decreasing order of probabilty.
+Alphanumeric characters and `!#?;~_` are reserved.
diff --git a/pub/doc/tools/tree.md b/pub/doc/tools/tree.md
new file mode 100644
index 000000000..e170b2eda
--- /dev/null
+++ b/pub/doc/tools/tree.md
@@ -0,0 +1,50 @@
+# `:tree`
+
+`:tree` is the web filesystem interface.
+
+`:tree` is a single-page app that uses a backend in `/home/tree` to load contents from `%clay` as the user navigates around as `%json`. The frontend lives in `/home/pub/tree` and is a fairly straightforward [React](https://facebook.github.io/react/) / [Flux](https://facebook.github.io/flux/) app.
+
+## Frontend
+
+The frontend code for `:tree` can be found in `/home/pub/tree/src/`.
+
+### CSS
+
+The CSS is written in [Stylus](https://learnboost.github.io/stylus/). The main entry point is `main.styl` and can be compiled with `stylus main.styl` which should output a `main.css`
+
+### JS
+
+The JS is written in [CoffeeScript](http://coffeescript.org/) and packaged with [Browserify](http://browserify.org/). The main entry point is `main.coffee` and is compiled with `browserify -t coffeeify main.coffee > main.js`. You'll need to `npm install` first.
+
+Each page is loaded as JSON and then rendered using React on the page. This allows us to write JSX in our markdown to implement simple components. Check out `/home/pub/tree/src/js/components` to see the component library.
+
+You'll notice that some of these doc pages use things like `` in the raw markdown files.
+
+## JSON API
+Async provides loading by schema
+
+`{path name sein sibs next prev}` are all immediately accesible from the store
+
+a `getPath` method, if present (defaulting to current url), is used to determine the query root node.
+
+## JSON Internals
+
+### `/[desk]/tree/{path}.json`
+`tree/json.hook` accepts a query string schema `q` in light noun encoding
+
+ ++ schema (dict ,[term $|(mark schema)])
+ ++ dict |*(a=_,* $&([a (dict a)] a))
+
+which is normalized and type-checked to a `query` list of
+- `[%kids query]`, the only recursive value, which executes for all subpaths
+ XX descent is only currently supported to a single level as a performance optimization
+- `[%name %t]`, the node name
+- `[%path %t]`, the current path
+- `[%snip %r]`, a snippet, extracted via `react-snip-json`
+- `[%head %r]`, the first ``, extracted via `react-head-json`
+- `[%body %r]`, the `react-json` body
+- `[%meta %j]`, json frontmatter per the `mdy` mark definition
+
+The request types above are `%t` text, `%r` html-derived tree, and `%j`
+arbitrary json; an example query, used by the main content renderer, is
+`"q=body.r__kids_name.t"` (`body:'r' kids:{name:'t'}` )
diff --git a/pub/doc/tree.md b/pub/doc/tree.md
deleted file mode 100644
index fa6f071f0..000000000
--- a/pub/doc/tree.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# Tree
-
-`:tree` is the web filesystem interface.
-
-# Data retrieval interface
-Async provides loading by schema
-
-`{path name sein sibs next prev}` are all immediately accesible from the store
-
-a `getPath` method, if present (defaulting to current url), is used to determine the query root node.
-
-# Internals
-
-something something coffeescript
-
-## `/[desk]/tree/{path}.json`
-tree/json.hook accepts a query string schema `q` in light noun encoding
-
- ++ schema (dict ,[term $|(mark schema)])
- ++ dict |*(a=_,* $&([a (dict a)] a))
-
-which is normalized and type-checked to a `query` list of
-- `[%kids query]`, the only recursive value, which executes for all subpaths
- XX descent is only currently supported to a single level as a performance optimization
-- `[%name %t]`, the node name
-- `[%path %t]`, the current path
-- `[%snip %r]`, a snippet, extracted via `react-snip-json`
-- `[%head %r]`, the first ``, extracted via `react-head-json`
-- `[%body %r]`, the `react-json` body
-- `[%meta %j]`, json frontmatter per the `mdy` mark definition
-
-The request types above are `%t` text, `%r` html-derived tree, and `%j`
-arbitrary json; an example query, used by the main content renderer, is
-`"q=body.r__kids_name.t"` (`body:'r' kids:{name:'t'}` )
diff --git a/pub/tree/src/js/components/ListComponent.coffee b/pub/tree/src/js/components/ListComponent.coffee
index 72b3784f8..8aead2503 100644
--- a/pub/tree/src/js/components/ListComponent.coffee
+++ b/pub/tree/src/js/components/ListComponent.coffee
@@ -37,12 +37,17 @@ module.exports = query {
elem = @props.kids[item]
href = window.tree.basepath path
parts = []
+ title = null
if elem.meta?.title
title =
gn: 'h1'
c: [elem.meta.title]
- else title = elem.head
- title ||= (h1 {},item)
+ if elem.head.c.length > 0
+ title = elem.head
+ if not title
+ title =
+ gn: 'h1'
+ c: [item]
parts.push title
unless @props.titlesOnly # redundant? this seems familiar
if @props.dataPreview
diff --git a/pub/tree/src/js/main.js b/pub/tree/src/js/main.js
index ad8c8aa38..b34a4d7c9 100644
--- a/pub/tree/src/js/main.js
+++ b/pub/tree/src/js/main.js
@@ -646,15 +646,22 @@ module.exports = query({
elem = this.props.kids[item];
href = window.tree.basepath(path);
parts = [];
+ title = null;
if ((ref4 = elem.meta) != null ? ref4.title : void 0) {
title = {
gn: 'h1',
c: [elem.meta.title]
};
- } else {
+ }
+ if (elem.head.c.length > 0) {
title = elem.head;
}
- title || (title = h1({}, item));
+ if (!title) {
+ title = {
+ gn: 'h1',
+ c: [item]
+ };
+ }
parts.push(title);
if (!this.props.titlesOnly) {
if (this.props.dataPreview) {