From ff4e20d63f6654102fb82a45ed676206c2be4cc7 Mon Sep 17 00:00:00 2001
From: Philip C Monk <philip.monk@tlon.io>
Date: Wed, 13 May 2015 17:18:43 -0400
Subject: [PATCH 01/12] fixed merges

---
 v/reck.c |   5 +-
 v/unix.c | 331 +++++++++++++++++++++++++++----------------------------
 2 files changed, 165 insertions(+), 171 deletions(-)

diff --git a/v/reck.c b/v/reck.c
index 7d4a6eac4..16a5f28be 100644
--- a/v/reck.c
+++ b/v/reck.c
@@ -485,8 +485,6 @@ u3_reck_kick(u3_noun ovo)
   if ( (c3n == _reck_kick_spec(u3k(u3h(ovo)), u3k(u3t(ovo)))) &&
        (c3n == _reck_kick_norm(u3k(u3h(ovo)), u3k(u3t(ovo)))) )
   {
-    u3_noun tox = u3do("spat", u3k(u3h(ovo)));
-
 #if 0
     if ( (c3__warn != u3h(u3t(ovo))) &&
          (c3__text != u3h(u3t(ovo))) &&
@@ -504,9 +502,11 @@ u3_reck_kick(u3_noun ovo)
                  u3nc(c3__flog, u3k(u3t(ovo))));
     }
     else {
+      u3_noun tox = u3do("spat", u3k(u3h(ovo)));
       uL(fprintf(uH, "kick: lost %%%s on %s\n",
                      u3r_string(u3h(u3t(ovo))),
                      u3r_string(tox)));
+      u3z(tox);
 #if 0
       if ( c3__hear == u3h(u3t(ovo)) ) {
         c3_assert(0);
@@ -514,7 +514,6 @@ u3_reck_kick(u3_noun ovo)
 #endif
     }
 #endif
-    u3z(tox);
   }
   u3z(ovo);
 }
diff --git a/v/unix.c b/v/unix.c
index f411838d1..cbf98e58d 100644
--- a/v/unix.c
+++ b/v/unix.c
@@ -21,6 +21,9 @@
 #include "all.h"
 #include "v/vere.h"
 
+/* undef this to turn off syncing out to unix */
+#define ERGO_SYNC
+
 /* _unix_ship_in(): c3_w[4] to ship.
 */
 static u3_noun
@@ -82,42 +85,6 @@ _unix_mkdir(c3_c* pax_c)
   }
 }
 
-/* _unix_mkpath(): mkdir -p, asserting
- *
- * adapted from
- * http://niallohiggins.com/2009/01/08/mkpath-mkdir-p-alike-in-c-for-unix/
- */
-static void
-_unix_mkpath(const char *s)
-{
-  char *q, *r = NULL, *path = NULL, *up = NULL;
-
-  if (strcmp(s, ".") == 0 || strcmp(s, "/") == 0)
-    return;
-
-  if ((path = strdup(s)) == NULL)
-    c3_assert(0);
-
-  if ((q = strdup(s)) == NULL)
-    c3_assert(0);
-
-  if ((r = dirname(q)) == NULL)
-    goto out;
-
-  if ((up = strdup(r)) == NULL)
-    exit(1);
-
-  _unix_mkpath(up);
-
-  _unix_mkdir(path);
-
-out:
-  if (up != NULL)
-    free(up);
-  free(q);
-  free(path);
-}
-
 /* _unix_opendir(): opendir, recreating if nonexistent.
 */
 static DIR*
@@ -137,17 +104,6 @@ _unix_opendir(c3_c* pax_c)
   return rid_u;
 }
 
-/* _unix_unlink(): unlink, asserting.
-*/
-static void
-_unix_unlink(c3_c* pax_c)
-{
-  if ( 0 != unlink(pax_c) && ENOENT != errno ) {
-    uL(fprintf(uH, "error unlinking %s: %s\n", pax_c, strerror(errno)));
-    c3_assert(0);
-  }
-}
-
 /* u3_unix_acquire(): acquire a lockfile, killing anything that holds it.
 */
 void
@@ -332,38 +288,6 @@ _unix_file_watch(u3_ufil* fil_u,
 
 }
 
-/* _unix_file_form(): form a filename path downward.
-*/
-static c3_c*
-_unix_file_form(c3_c* pax_c,
-                u3_noun  pre,
-                u3_noun  ket,
-                u3_noun  ext)
-{
-  c3_c* pre_c = u3r_string(pre);
-  c3_c* ext_c = u3r_string(ext);
-  c3_w  pax_w = strlen(pax_c);
-  c3_w  pre_w = strlen(pre_c);
-  c3_w  ext_w = strlen(ext_c);
-  c3_w  ket_w = (c3y == ket) ? 1 : 0;
-  c3_c* pox_c = c3_malloc(pax_w + 1 + pre_w + 1 + ket_w + ext_w + 1);
-
-  strncpy(pox_c, pax_c, pax_w);
-  pox_c[pax_w] = '/';
-  strncpy(pox_c + pax_w + 1, pre_c, pre_w);
-  pox_c[pax_w + 1 + pre_w] = '.';
-  if ( c3y == ket ) {
-    pox_c[pax_w + 1 + pre_w + 1] = '^';
-  }
-  strncpy(pox_c + pax_w + 1 + pre_w + 1 + ket_w, ext_c, ext_w);
-  pox_c[pax_w + 1 + pre_w + 1 + ket_w + ext_w] = '\0';
-
-  free(pre_c); free(ext_c);
-  u3z(pre); u3z(ext);
-
-  return pox_c;
-}
-
 /* _unix_dir_watch(): instantiate directory tracker.
 */
 static void
@@ -402,35 +326,6 @@ _unix_dir_watch(u3_udir* dir_u, u3_udir* par_u, c3_c* pax_c, c3_c* pot_c)
 
 }
 
-/* _unix_dir_forge: instantiate directory tracker (and make directory).
-*/
-static void
-_unix_dir_forge(u3_udir* dir_u, u3_udir* par_u, u3_noun tet)
-{
-  c3_c* tet_c = u3r_string(tet);
-  c3_w  pax_w = strlen(par_u->pax_c);
-  c3_w  tet_w = strlen(tet_c);
-  c3_c* pax_c = c3_malloc(pax_w + 1 + tet_w + 1);
-  c3_c* pot_c = c3_malloc(pax_w + 1 + 1 + tet_w + 1);
-
-  strncpy(pax_c, par_u->pax_c, pax_w + 1);
-  pax_c[pax_w] = '/';
-  strncpy(pax_c + pax_w + 1, tet_c, tet_w + 1);
-  pax_c[pax_w + tet_w + 1] = '\0';
-
-  strncpy(pot_c, par_u->pot_c, pax_w + 1 + 1);
-  pot_c[pax_w + 1] = '/';
-  strncpy(pot_c + pax_w + 1 + 1, tet_c, tet_w + 1);
-  pot_c[pax_w + 1 + tet_w + 1] = '\0';
-
-  free(tet_c);
-  u3z(tet);
-
-  _unix_mkdir(pax_c);
-  _unix_mkdir(pot_c);
-  _unix_dir_watch(dir_u, par_u, pax_c, pot_c);
-}
-
 /* _unix_file_done(): finish freeing file.
 */
 static void
@@ -741,42 +636,6 @@ _unix_load(u3_ufil* fil_u)
   }
 }
 
-/* unix_save(): save a file.
-*/
-static void
-_unix_save(c3_c* pax_c, u3_atom oat)
-{
-  c3_c* dir = strdup(pax_c);
-  _unix_mkpath(dirname(dir));
-  free(dir);
-
-  c3_i  fid_i = open(pax_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
-  c3_w  fln_w, rit_w, siz_w;
-  c3_y* oat_y;
-
-  if ( fid_i < 0 ) {
-    uL(fprintf(uH, "error opening %s: %s\n", pax_c, strerror(errno)));
-    u3m_bail(c3__fail);
-  }
-
-  siz_w = u3h(u3t(oat));
-  fln_w = u3r_met(3, u3t(u3t(oat)));
-  oat_y = c3_malloc(siz_w);
-  memset(oat_y, 0, siz_w);
-
-  u3r_bytes(0, fln_w, oat_y, u3t(u3t(oat)));
-  u3z(oat);
-
-  rit_w = write(fid_i, oat_y, siz_w);
-  if ( rit_w != siz_w ) {
-    uL(fprintf(uH, "error writing %s: %s\n", pax_c, strerror(errno)));
-    c3_assert(0);
-  }
-
-  close(fid_i);
-  free(oat_y);
-}
-
 /* _unix_file_load(): load a file by watcher.
 */
 static u3_weak
@@ -1201,6 +1060,134 @@ _unix_hot_lose(u3_uhot* hot_u)
   _unix_dir_free(&(hot_u->dir_u));
 }
 
+/* _unix_home(): find home directory from identity.
+*/
+static u3_uhot*
+_unix_home(u3_noun who)
+{
+  u3_unix* unx_u = &u3_Host.unx_u;
+  u3_uhot* hot_u;
+  c3_w     who_w[4];
+
+  _unix_ship_out(who, who_w);
+  for ( hot_u = unx_u->hot_u;
+        hot_u && !_(_unix_ship_sing(who_w, hot_u->who_w));
+        hot_u = hot_u->nex_u )
+  {
+    // uL(fprintf(uH, "uh: %p, %s\n", hot_u, hot_u->dir_u.pax_c));
+  }
+  return hot_u;
+}
+
+#ifdef ERGO_SYNC
+/* _unix_mkpath(): mkdir -p, asserting
+ *
+ * adapted from
+ * http://niallohiggins.com/2009/01/08/mkpath-mkdir-p-alike-in-c-for-unix/
+ */
+static void
+_unix_mkpath(const char *s)
+{
+  char *q, *r = NULL, *path = NULL, *up = NULL;
+
+  if (strcmp(s, ".") == 0 || strcmp(s, "/") == 0)
+    return;
+
+  if ((path = strdup(s)) == NULL)
+    c3_assert(0);
+
+  if ((q = strdup(s)) == NULL)
+    c3_assert(0);
+
+  if ((r = dirname(q)) == NULL)
+    goto out;
+
+  if ((up = strdup(r)) == NULL)
+    exit(1);
+
+  _unix_mkpath(up);
+
+  _unix_mkdir(path);
+
+out:
+  if (up != NULL)
+    free(up);
+  free(q);
+  free(path);
+}
+
+/* _unix_dir_forge: instantiate directory tracker (and make directory).
+*/
+static void
+_unix_dir_forge(u3_udir* dir_u, u3_udir* par_u, u3_noun tet)
+{
+  c3_c* tet_c = u3r_string(tet);
+  c3_w  pax_w = strlen(par_u->pax_c);
+  c3_w  tet_w = strlen(tet_c);
+  c3_c* pax_c = c3_malloc(pax_w + 1 + tet_w + 1);
+  c3_c* pot_c = c3_malloc(pax_w + 1 + 1 + tet_w + 1);
+
+  strncpy(pax_c, par_u->pax_c, pax_w + 1);
+  pax_c[pax_w] = '/';
+  strncpy(pax_c + pax_w + 1, tet_c, tet_w + 1);
+  pax_c[pax_w + tet_w + 1] = '\0';
+
+  strncpy(pot_c, par_u->pot_c, pax_w + 1 + 1);
+  pot_c[pax_w + 1] = '/';
+  strncpy(pot_c + pax_w + 1 + 1, tet_c, tet_w + 1);
+  pot_c[pax_w + 1 + tet_w + 1] = '\0';
+
+  free(tet_c);
+  u3z(tet);
+
+  _unix_mkdir(pax_c);
+  _unix_mkdir(pot_c);
+  _unix_dir_watch(dir_u, par_u, pax_c, pot_c);
+}
+
+/* _unix_file_form(): form a filename path downward.
+*/
+static c3_c*
+_unix_file_form(c3_c* pax_c,
+                u3_noun  pre,
+                u3_noun  ket,
+                u3_noun  ext)
+{
+  c3_c* pre_c = u3r_string(pre);
+  c3_c* ext_c = u3r_string(ext);
+  c3_w  pax_w = strlen(pax_c);
+  c3_w  pre_w = strlen(pre_c);
+  c3_w  ext_w = strlen(ext_c);
+  c3_w  ket_w = (c3y == ket) ? 1 : 0;
+  c3_c* pox_c = c3_malloc(pax_w + 1 + pre_w + 1 + ket_w + ext_w + 1);
+
+  strncpy(pox_c, pax_c, pax_w);
+  pox_c[pax_w] = '/';
+  strncpy(pox_c + pax_w + 1, pre_c, pre_w);
+  pox_c[pax_w + 1 + pre_w] = '.';
+  if ( c3y == ket ) {
+    pox_c[pax_w + 1 + pre_w + 1] = '^';
+  }
+  strncpy(pox_c + pax_w + 1 + pre_w + 1 + ket_w, ext_c, ext_w);
+  pox_c[pax_w + 1 + pre_w + 1 + ket_w + ext_w] = '\0';
+
+  free(pre_c); free(ext_c);
+  u3z(pre); u3z(ext);
+
+  return pox_c;
+}
+
+/* _unix_unlink(): unlink, asserting.
+*/
+static void
+_unix_unlink(c3_c* pax_c)
+{
+  if ( 0 != unlink(pax_c) && ENOENT != errno ) {
+    uL(fprintf(uH, "error unlinking %s: %s\n", pax_c, strerror(errno)));
+    c3_assert(0);
+  }
+}
+
 /* _unix_pdir(): find directory reference from text.
 */
 static u3_udir**
@@ -1221,34 +1208,41 @@ _unix_pdir(u3_udir* par_u, u3_noun tet)
   }
 }
 
-/* _unix_home(): find home directory from identity.
+/* unix_save(): save a file.
 */
-static u3_uhot*
-_unix_home(u3_noun who)
+static void
+_unix_save(c3_c* pax_c, u3_atom oat)
 {
-  u3_unix* unx_u = &u3_Host.unx_u;
-  u3_uhot* hot_u;
-  c3_w     who_w[4];
+  c3_c* dir = strdup(pax_c);
+  _unix_mkpath(dirname(dir));
+  free(dir);
 
-  _unix_ship_out(who, who_w);
-  for ( hot_u = unx_u->hot_u;
-        hot_u && !_(_unix_ship_sing(who_w, hot_u->who_w));
-        hot_u = hot_u->nex_u )
-  {
-    // uL(fprintf(uH, "uh: %p, %s\n", hot_u, hot_u->dir_u.pax_c));
+  c3_i  fid_i = open(pax_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+  c3_w  fln_w, rit_w, siz_w;
+  c3_y* oat_y;
+
+  if ( fid_i < 0 ) {
+    uL(fprintf(uH, "error opening %s: %s\n", pax_c, strerror(errno)));
+    u3m_bail(c3__fail);
   }
-  return hot_u;
-}
 
-#if 0
-/* _unix_desk_sync_udon(): apply udon to existing value.
-*/
-static u3_noun
-_unix_desk_sync_udon(u3_noun don, u3_noun old)
-{
-  return u3dc("lump", don, old);
+  siz_w = u3h(u3t(oat));
+  fln_w = u3r_met(3, u3t(u3t(oat)));
+  oat_y = c3_malloc(siz_w);
+  memset(oat_y, 0, siz_w);
+
+  u3r_bytes(0, fln_w, oat_y, u3t(u3t(oat)));
+  u3z(oat);
+
+  rit_w = write(fid_i, oat_y, siz_w);
+  if ( rit_w != siz_w ) {
+    uL(fprintf(uH, "error writing %s: %s\n", pax_c, strerror(errno)));
+    c3_assert(0);
+  }
+
+  close(fid_i);
+  free(oat_y);
 }
-#endif
 
 /* _unix_desk_sync_tofu(): sync out file install.
 */
@@ -1420,6 +1414,7 @@ _unix_desk_sync_list(u3_udir* dir_u, u3_noun can)
 
   u3z(can);
 }
+#endif
 
 /* _unix_desk_sync_ergo(): sync desk changes to unix.
 */
@@ -1430,11 +1425,11 @@ _unix_desk_sync_ergo(u3_noun  hox,
                      u3_noun  can,
                      u3_uhot* hot_u)
 {
-#if 0
+#ifndef ERGO_SYNC
   u3z(hox); u3z(syd); u3z(lok); u3z(can);
 #else
 
-  u3_udir** dir_u = _unix_pdir(&(hot_u->dir_u), syd);
+  u3_udir** dir_u = _unix_pdir(&(hot_u->dir_u), u3k(syd));
 
 #if 0
   uL(fprintf(uH, "ergo %s %s %s\n", u3r_string(hox),

From c1261be063cb4641eac899afb5a0f1436d197eaf Mon Sep 17 00:00:00 2001
From: Philip C Monk <philip.monk@tlon.io>
Date: Thu, 14 May 2015 13:49:22 -0400
Subject: [PATCH 02/12] temporarily changed ~zod's address

---
 v/ames.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/v/ames.c b/v/ames.c
index 391032fcb..0588a5ed6 100644
--- a/v/ames.c
+++ b/v/ames.c
@@ -65,7 +65,12 @@ _ames_czar(c3_y imp_y, c3_s* por_s)
       c3_c*   nam_c = u3r_string(nam);
       c3_c    dns_c[64];
 
-      snprintf(dns_c, 64, "%s.urbit.org", nam_c + 1);
+      if ( 0 == imp_y ) {
+        strcpy(dns_c,"104.236.149.223");
+      }
+      else {
+        snprintf(dns_c, 64, "%s.urbit.org", nam_c + 1);
+      }
       // uL(fprintf(uH, "czar %s, dns %s\n", nam_c, dns_c));
       free(nam_c);
       u3z(nam);

From 2b861da97c84542498ba8e2c1f01d423da8024bd Mon Sep 17 00:00:00 2001
From: "C. Guy Yarvin" <cgyarvin@gmail.com>
Date: Sat, 16 May 2015 17:31:28 -0700
Subject: [PATCH 03/12] drum in hood works, modulo slow update bug.

---
 n/a.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/n/a.c b/n/a.c
index 7d505b8d8..d03b6847d 100644
--- a/n/a.c
+++ b/n/a.c
@@ -963,11 +963,11 @@ _me_copy_south(u3_noun dog)
         u3a_cell* new_u = (u3a_cell*)(void *)new_w;
 
         // printf("south: cell %p to %p\r\n", old_u, new_u);
-
+#if 0
         if ( old_u->mug_w == 0x730e66cc ) {
           fprintf(stderr, "BAD: take %p\r\n", new_u);
         }
-
+#endif
         new_u->mug_w = old_u->mug_w;
         // new_u->mug_w = 0;
         new_u->hed = _me_copy_south_in(old_u->hed);

From 8caac67e05171dfa0e7e2f85529119553e14d9d1 Mon Sep 17 00:00:00 2001
From: "C. Guy Yarvin" <cgyarvin@gmail.com>
Date: Mon, 18 May 2015 10:07:42 -0700
Subject: [PATCH 04/12] Eliminated last direct pointers from piers.

---
 i/n/a.h |  8 +++-----
 i/n/u.h |  1 +
 n/j.c   |  4 ++--
 n/m.c   | 36 ++++++++++++++++++------------------
 n/t.c   |  6 +++---
 5 files changed, 27 insertions(+), 28 deletions(-)

diff --git a/i/n/a.h b/i/n/a.h
index 541e24e5f..23e62ebaf 100644
--- a/i/n/a.h
+++ b/i/n/a.h
@@ -98,11 +98,9 @@
     /* u3a_road: contiguous allocation and execution context.
     */
       typedef struct _u3a_road {
-        struct _u3a_road* par_u;              //  parent road
-
-        struct _u3a_road* kid_u;              //  child road list
-        struct _u3a_road* nex_u;              //  sibling road
-        struct _u3a_road* now_u;              //  current road pointer
+        u3p(struct _u3a_road) par_p;          //  parent road
+        u3p(struct _u3a_road) kid_p;          //  child road list
+        u3p(struct _u3a_road) nex_p;          //  sibling road
 
         u3p(c3_w) cap_p;                      //  top of transient region
         u3p(c3_w) hat_p;                      //  top of durable region
diff --git a/i/n/u.h b/i/n/u.h
index 9eb033ea3..46c9553af 100644
--- a/i/n/u.h
+++ b/i/n/u.h
@@ -104,5 +104,6 @@
     /* u3to(), u3of(): offset/pointer conversion.
     */
 #     define  u3to(type, x) ((type *) u3a_into(x))
+#     define  u3tn(type, x) (x == 0) ? (void *)0 :  ((type *) u3a_into(x))
 #     define  u3of(type, x) (u3a_outa((type *)x))
 
diff --git a/n/j.c b/n/j.c
index 0e6db22b2..acc70703a 100644
--- a/n/j.c
+++ b/n/j.c
@@ -209,8 +209,8 @@ u3j_find(u3_noun bat)
       return jaw;
     }
 
-    if ( rod_u->par_u ) {
-      rod_u = rod_u->par_u;
+    if ( rod_u->par_p ) {
+      rod_u = u3to(u3_road, rod_u->par_p);
     }
     else return u3_none;
   }
diff --git a/n/m.c b/n/m.c
index d99f6872d..d2c85dd4b 100644
--- a/n/m.c
+++ b/n/m.c
@@ -149,7 +149,7 @@ _cm_signal_handle_term(int x)
 {
   //  Ignore if we are using base memory from work memory, very rare.
   //
-  if ( (0 != u3H->rod_u.kid_u) && (&(u3H->rod_u) == u3R) ) {
+  if ( (0 != u3H->rod_u.kid_p) && (&(u3H->rod_u) == u3R) ) {
     _cm_emergency("ignored", c3__term);
   }
   else {
@@ -184,7 +184,7 @@ _cm_signal_reset(void)
   u3R = &u3H->rod_u;
   u3R->cap_p = u3R->mat_p;
   u3R->ear_p = 0;
-  u3R->kid_u = 0;
+  u3R->kid_p = 0;
 }
 
 /* _cm_stack_recover(): recover stack trace, with lacunae.
@@ -276,13 +276,13 @@ _cm_signal_recover(c3_l sig_l, u3_noun arg)
       u3R = &(u3H->rod_u);
       rod_u = u3R;
  
-      while ( rod_u->kid_u ) {
+      while ( rod_u->kid_p ) {
 #if 0
         fprintf(stderr, "collecting %d frames\r\n", 
-              u3kb_lent(rod_u->kid_u->bug.tax));
+              u3kb_lent((u3to(u3_road, rod_u->kid_p)->bug.tax));
 #endif
-        tax = u3kb_weld(_cm_stack_recover(rod_u->kid_u), tax);    
-        rod_u = rod_u->kid_u;
+        tax = u3kb_weld(_cm_stack_recover(u3to(u3_road, rod_u->kid_p)), tax);
+        rod_u = u3to(u3_road, rod_u->kid_p);
       }
     }
 
@@ -712,9 +712,9 @@ u3m_leap(c3_w pad_w)
   /* Attach the new road to its parents.
   */
   {
-    c3_assert(0 == u3R->kid_u);
-    rod_u->par_u = u3R;
-    u3R->kid_u = rod_u;
+    c3_assert(0 == u3R->kid_p);
+    rod_u->par_p = u3of(u3_road, u3R);
+    u3R->kid_p = u3of(u3_road, rod_u);
   }
 
   /* Set up the new road.
@@ -730,26 +730,26 @@ u3m_leap(c3_w pad_w)
 void
 u3m_fall()
 {
-  c3_assert(0 != u3R->par_u);
+  c3_assert(0 != u3R->par_p);
 
 #if 0
   fprintf(stderr, "fall: from %s %p, to %s %p (cap %p, was %p)\r\n",
           _(u3a_is_north(u3R)) ? "north" : "south",
           u3R,
           _(u3a_is_north(u3R)) ? "north" : "south",
-          u3R->par_u,
+          u3to(u3_road, u3R->par_p),
           u3R->hat_w,
           u3R->rut_w);
 #endif
 
   /* The new cap is the old hat - it's as simple as that.
   */
-  u3R->par_u->cap_p = u3R->hat_p;
+  u3to(u3_road, u3R->par_p)->cap_p = u3R->hat_p;
 
   /* And, we're back home.
   */
-  u3R = u3R->par_u;
-  u3R->kid_u = 0;
+  u3R = u3to(u3_road, u3R->par_p);
+  u3R->kid_p = 0;
 }
 
 /* u3m_hate(): new, integrated leap mechanism (enter).
@@ -951,8 +951,8 @@ u3m_soft_run(u3_noun fly,
   /* Configure the new road.
   */
   {
-    u3R->ski.flu = u3nc(fly, u3R->par_u->ski.flu);
-    u3R->pro.don = u3R->par_u->pro.don;
+    u3R->ski.flu = u3nc(fly, u3to(u3_road, u3R->par_p)->ski.flu);
+    u3R->pro.don = u3to(u3_road, u3R->par_p)->pro.don;
     u3R->bug.tax = 0;
   }
   u3t_on(coy_o);
@@ -1039,8 +1039,8 @@ u3m_soft_esc(u3_noun sam)
   /* Configure the new road.
   */
   {
-    u3R->ski.flu = u3t(u3R->par_u->ski.flu);
-    u3R->pro.don = u3R->par_u->pro.don;
+    u3R->ski.flu = u3t(u3to(u3_road, u3R->par_p)->ski.flu);
+    u3R->pro.don = u3to(u3_road, u3R->par_p)->pro.don;
     u3R->bug.tax = 0;
   }
 
diff --git a/n/t.c b/n/t.c
index eeefb0ca3..ff937334b 100644
--- a/n/t.c
+++ b/n/t.c
@@ -113,8 +113,8 @@ _t_jet_label(u3a_road* rod_u, u3_noun bat)
       return u3h(u3t(u3t(u3h(cax))));
     }
 
-    if ( rod_u->par_u ) {
-      rod_u = rod_u->par_u;
+    if ( rod_u->par_p ) {
+      rod_u = u3to(u3_road, rod_u->par_p);
     }
     else return u3_none;
   }
@@ -175,7 +175,7 @@ _t_samp_process(u3_road* rod_u)
       }
       don = u3t(don);
     }
-    rod_u = rod_u->par_u;
+    rod_u = u3tn(u3_road, rod_u->par_p);
   }
   u3z(muf);
   

From d31186b021fca747843115a0a4e4cd7d26e75d9b Mon Sep 17 00:00:00 2001
From: "C. Guy Yarvin" <cgyarvin@gmail.com>
Date: Mon, 18 May 2015 13:14:27 -0700
Subject: [PATCH 05/12] Revert dual network.

---
 v/ames.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/v/ames.c b/v/ames.c
index 0588a5ed6..b48c1d5d2 100644
--- a/v/ames.c
+++ b/v/ames.c
@@ -65,13 +65,9 @@ _ames_czar(c3_y imp_y, c3_s* por_s)
       c3_c*   nam_c = u3r_string(nam);
       c3_c    dns_c[64];
 
-      if ( 0 == imp_y ) {
-        strcpy(dns_c,"104.236.149.223");
-      }
-      else {
-        snprintf(dns_c, 64, "%s.urbit.org", nam_c + 1);
-      }
+      snprintf(dns_c, 64, "%s.urbit.org", nam_c + 1);
       // uL(fprintf(uH, "czar %s, dns %s\n", nam_c, dns_c));
+
       free(nam_c);
       u3z(nam);
 

From ad47ebec566d8cc7f195d0d6224983d3c4c6be79 Mon Sep 17 00:00:00 2001
From: "C. Guy Yarvin" <cgyarvin@gmail.com>
Date: Tue, 19 May 2015 11:38:23 -0700
Subject: [PATCH 06/12] -T for autoboot.

---
 Makefile   | 26 +++++++++++++-------------
 i/v/vere.h |  7 +++++++
 v/loop.c   |  3 +++
 v/main.c   | 24 +++++++++++++++++++++++-
 v/term.c   | 26 ++++++++++++++++++++++++++
 5 files changed, 72 insertions(+), 14 deletions(-)

diff --git a/Makefile b/Makefile
index c94d85fdc..c0ea4e07d 100644
--- a/Makefile
+++ b/Makefile
@@ -354,7 +354,7 @@ LIBCOMMONMARK=outside/commonmark/build/src/libcmark.a
 
 LIBSCRYPT=outside/scrypt/scrypt.a
 
-all: vere
+all: urbit
 
 .MAKEFILE-VERSION: Makefile .make.conf
 	@echo "Makefile update."
@@ -363,7 +363,7 @@ all: vere
 .make.conf:
 	@echo "# Set custom configuration here, please!" > ".make.conf"
 
-vere: $(BIN)/vere
+urbit: $(BIN)/urbit
 meme: $(BIN)/meme
 
 $(LIBUV_MAKEFILE) $(LIBUV_MAKEFILE2):
@@ -393,14 +393,14 @@ $(CRE2_OFILES): outside/cre2/src/src/cre2.cpp outside/cre2/src/src/cre2.h $(LIBR
 $(V_OFILES): i/v/vere.h
 
 ifdef NO_SILENT_RULES
-$(BIN)/vere: $(LIBCRE) $(LIBCOMMONMARK) $(VERE_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT)
+$(BIN)/urbit: $(LIBCRE) $(LIBCOMMONMARK) $(VERE_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT)
 	mkdir -p $(BIN)
-	$(CLD) $(CLDOSFLAGS) -o $(BIN)/vere $(VERE_OFILES) $(LIBUV) $(LIBCRE) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBS) $(LIBCOMMONMARK) $(LIBSCRYPT)
+	$(CLD) $(CLDOSFLAGS) -o $(BIN)/urbit $(VERE_OFILES) $(LIBUV) $(LIBCRE) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBS) $(LIBCOMMONMARK) $(LIBSCRYPT)
 else
-$(BIN)/vere: $(LIBCRE) $(LIBCOMMONMARK) $(VERE_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT)
-	@echo "    CCLD  $(BIN)/vere"
+$(BIN)/urbit: $(LIBCRE) $(LIBCOMMONMARK) $(VERE_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT)
+	@echo "    CCLD  $(BIN)/urbit"
 	@mkdir -p $(BIN)
-	@$(CLD) $(CLDOSFLAGS) -o $(BIN)/vere $(VERE_OFILES) $(LIBUV) $(LIBCRE) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBS) $(LIBCOMMONMARK) $(LIBSCRYPT)
+	@$(CLD) $(CLDOSFLAGS) -o $(BIN)/urbit $(VERE_OFILES) $(LIBUV) $(LIBCRE) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBS) $(LIBCOMMONMARK) $(LIBSCRYPT)
 endif
 
 $(BIN)/meme: $(LIBCRE) $(LIBCOMMONMARK) $(MEME_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT)
@@ -416,24 +416,24 @@ etags:
 osxpackage:
 	$(RM) -r inst
 	$(MAKE) distclean
-	$(MAKE) $(BIN)/vere LIB=/usr/local/lib/urb STATIC=yes
+	$(MAKE) $(BIN)/urbit LIB=/usr/local/lib/urb STATIC=yes
 	mkdir -p inst/usr/local/lib/urb inst/usr/local/bin
-	cp $(BIN)/vere inst/usr/local/bin
+	cp $(BIN)/urbit inst/usr/local/bin
 	cp urb/urbit.pill inst/usr/local/lib/urb
 	cp -R urb/zod inst/usr/local/lib/urb
-	pkgbuild --root inst --identifier org.urbit.vere --version 0.2 vere.pkg
+	pkgbuild --root inst --identifier org.urbit.urbit --version 0.2 urbit.pkg
 
 debbuild:
-	$(MAKE) $(BIN)/vere LIB=/usr/share/urb
+	$(MAKE) $(BIN)/urbit LIB=/usr/share/urb
 
 debinstall:
 	mkdir -p $(DESTDIR)/usr/bin $(DESTDIR)/usr/share/urb
-	install -m755 $(BIN)/vere $(DESTDIR)/usr/bin
+	install -m755 $(BIN)/urbit $(DESTDIR)/usr/bin
 	cp urb/urbit.pill $(DESTDIR)/usr/share/urb
 	cp -R urb/zod $(DESTDIR)/usr/share/urb
 
 clean: 
-	$(RM) $(VERE_OFILES) $(BIN)/vere vere.pkg $(VERE_DFILES)
+	$(RM) $(VERE_OFILES) $(BIN)/urbit urbit.pkg $(VERE_DFILES)
 
 distclean: clean $(LIBUV_MAKEFILE)
 	$(MAKE) -C outside/libuv_0.11 distclean
diff --git a/i/v/vere.h b/i/v/vere.h
index 9acf5ad7c..39997d462 100644
--- a/i/v/vere.h
+++ b/i/v/vere.h
@@ -521,6 +521,8 @@
         c3_c*   imp_c;                      //  -I, czar name
         c3_c*   nam_c;                      //  -n, unix hostname
         c3_c*   raf_c;                      //  -r, raft flotilla
+        c3_c*   who_c;                      //  -T, begin with ticket
+        c3_c*   tic_c;                      //  -T, ticket value
         c3_w    kno_w;                      //  -k, kernel version
         c3_w    fuz_w;                      //  -f, fuzz testing
         c3_s    por_s;                      //  -p, ames port
@@ -791,6 +793,11 @@
         void
         u3_term_ef_boil();
 
+      /* u3_term_ef_ticket(): initial effects for new ticket.
+      */
+        void
+        u3_term_ef_ticket(c3_c* who_c, c3_c* tic_c);
+
       /* u3_term_ef_winc(): window change.
       */
         void
diff --git a/v/loop.c b/v/loop.c
index 8103518f8..146265b82 100644
--- a/v/loop.c
+++ b/v/loop.c
@@ -691,6 +691,9 @@ u3_lo_lead(void)
 #endif
 
   if ( c3y == u3_Host.ops_u.nuu ) {
+    if ( u3_Host.ops_u.who_c ) {
+      u3_term_ef_ticket(u3_Host.ops_u.who_c, u3_Host.ops_u.tic_c);
+    }
     u3_term_ef_boil(1);
   }
 
diff --git a/v/main.c b/v/main.c
index 37bafcb34..a2a879251 100644
--- a/v/main.c
+++ b/v/main.c
@@ -40,6 +40,22 @@ _main_readw(const c3_c* str_c, c3_w max_w, c3_w* out_w)
 
 static c3_c hostbuf[2048];  // kill me
 
+/* _main_presig(): prefix optional sig.
+*/
+c3_c* 
+_main_presig(c3_c* txt_c)
+{
+  c3_c* new_c = malloc(2 + strlen(txt_c));
+
+  if ( '~' == *txt_c ) {
+    strcpy(new_c, txt_c);
+  } else {
+    new_c[0] = '~';
+    strcpy(new_c + 1, txt_c);
+  }
+  return new_c;
+}
+
 /* _main_getopt(): extract option map from command line.
 */
 static u3_noun
@@ -62,7 +78,7 @@ _main_getopt(c3_i argc, c3_c** argv)
   u3_Host.ops_u.mem = c3n;
   u3_Host.ops_u.kno_w = DefaultKernel;
 
-  while ( (ch_i = getopt(argc, argv, "I:X:f:k:l:n:p:r:LabcdgqvFMPD")) != -1 ) {
+  while ( (ch_i = getopt(argc, argv, "I:T:X:f:k:l:n:p:r:LabcdgqvFMPD")) != -1 ) {
     switch ( ch_i ) {
       case 'M': {
         u3_Host.ops_u.mem = c3y;
@@ -72,6 +88,11 @@ _main_getopt(c3_i argc, c3_c** argv)
         u3_Host.ops_u.imp_c = strdup(optarg);
         break;
       }
+      case 'T': {
+        u3_Host.ops_u.who_c = _main_presig(optarg);
+        u3_Host.ops_u.tic_c = _main_presig(getpass("your ticket: ~"));
+        break;
+      }
       case 'X': {
         if ( 0 != strcmp("wtf", optarg) ) {
           return c3n;
@@ -363,6 +384,7 @@ main(c3_i   argc,
   }
 
   // u3e_grab("main", u3_none);
+  //
   u3_lo_loop();
 
   return 0;
diff --git a/v/term.c b/v/term.c
index 7934df5b4..16df7cedb 100644
--- a/v/term.c
+++ b/v/term.c
@@ -1012,6 +1012,32 @@ u3_term_ef_boil(void)
   }
 }
 
+/* u3_term_ef_ticket(): initial effects for new ticket.
+*/
+void
+u3_term_ef_ticket(c3_c* who_c, c3_c* tic_c)
+{
+  u3_noun pax = u3nq(u3_blip, c3__term, '1', u3_nul);
+  u3_noun who, tic;
+  u3_noun whu, tuc; 
+  
+  whu = u3dc("slaw", 'p', u3i_string(who_c));
+  if ( u3_nul == whu ) {
+    fprintf(stderr, "ticket: invalid planet '%s'\r\n", who_c);
+    exit(1);
+  }
+  else { who = u3k(u3t(whu)); u3z(whu); }
+
+  tuc = u3dc("slaw", 'p', u3i_string(tic_c));
+  if ( u3_nul == tuc ) {
+    fprintf(stderr, "ticket: invalid secret '%s'\r\n", tic_c);
+    exit(1);
+  }
+  else { tic = u3k(u3t(tuc)); u3z(tuc); }
+
+  u3v_plan(pax, u3nt(c3__tick, who, tic));
+}
+
 /* u3_term_ef_bake(): initial effects for new terminal.
 */
 void

From 225d211f013bb0fcb0334fc24fe954ae6c1318af Mon Sep 17 00:00:00 2001
From: "C. Guy Yarvin" <cgyarvin@gmail.com>
Date: Tue, 19 May 2015 11:56:44 -0700
Subject: [PATCH 07/12] You can now start with -v.

---
 i/c/motes.h |  1 +
 i/v/vere.h  |  5 +++++
 v/loop.c    |  4 ++++
 v/main.c    |  2 +-
 v/term.c    | 10 ++++++++++
 5 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/i/c/motes.h b/i/c/motes.h
index e67ce0b21..ff56945fa 100644
--- a/i/c/motes.h
+++ b/i/c/motes.h
@@ -1121,6 +1121,7 @@
 #   define c3__veer   c3_s4('v','e','e','r')
 #   define c3__vega   c3_s4('v','e','g','a')
 #   define c3__velt   c3_s4('v','e','l','t')
+#   define c3__verb   c3_s4('v','e','r','b')
 #   define c3__vern   c3_s4('v','e','r','n')
 #   define c3__very   c3_s4('v','e','r','y')
 #   define c3__view   c3_s4('v','i','e','w')
diff --git a/i/v/vere.h b/i/v/vere.h
index 281fcb0a0..6f50c2863 100644
--- a/i/v/vere.h
+++ b/i/v/vere.h
@@ -798,6 +798,11 @@
         void
         u3_term_ef_ticket(c3_c* who_c, c3_c* tic_c);
 
+      /* u3_term_ef_verb(): initial effects for verbose events.
+      */
+        void
+        u3_term_ef_verb(void);
+
       /* u3_term_ef_winc(): window change.
       */
         void
diff --git a/v/loop.c b/v/loop.c
index 146265b82..8f4788a58 100644
--- a/v/loop.c
+++ b/v/loop.c
@@ -697,6 +697,10 @@ u3_lo_lead(void)
     u3_term_ef_boil(1);
   }
 
+  if ( c3y == u3_Host.ops_u.veb ) {
+    u3_term_ef_verb();
+  }
+
 #if 1
   _lo_slow();
 #endif
diff --git a/v/main.c b/v/main.c
index a2a879251..d1163ec06 100644
--- a/v/main.c
+++ b/v/main.c
@@ -73,7 +73,7 @@ _main_getopt(c3_i argc, c3_c** argv)
   u3_Host.ops_u.fak = c3n;
   u3_Host.ops_u.pro = c3n;
   u3_Host.ops_u.dry = c3n;
-  u3_Host.ops_u.veb = c3y;
+  u3_Host.ops_u.veb = c3n;
   u3_Host.ops_u.nuu = c3n;
   u3_Host.ops_u.mem = c3n;
   u3_Host.ops_u.kno_w = DefaultKernel;
diff --git a/v/term.c b/v/term.c
index 16df7cedb..0c2089d9c 100644
--- a/v/term.c
+++ b/v/term.c
@@ -1012,6 +1012,16 @@ u3_term_ef_boil(void)
   }
 }
 
+/* u3_term_ef_verb(): initial effects for verbose events
+*/
+void
+u3_term_ef_verb(void)
+{
+  u3_noun pax = u3nq(u3_blip, c3__term, '1', u3_nul);
+
+  u3v_plan(pax, u3nc(c3__verb, u3_nul));
+}
+
 /* u3_term_ef_ticket(): initial effects for new ticket.
 */
 void

From 384ab7b37e6c6b8f22de4029d6e2cf0b4f20944b Mon Sep 17 00:00:00 2001
From: Philip C Monk <philip.monk@tlon.io>
Date: Tue, 19 May 2015 18:43:12 -0400
Subject: [PATCH 08/12] add (disabled) bad event ignore

---
 v/sist.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/v/sist.c b/v/sist.c
index b2c29ea83..ff42b650b 100644
--- a/v/sist.c
+++ b/v/sist.c
@@ -222,9 +222,13 @@ _sist_suck(u3_noun ovo, u3_noun gon)
 
   u3_lo_punt(2, u3kb_flop(u3k(u3t(gon))));
   // u3_loom_exit();
+#if 1
   u3_lo_exit();
 
   exit(1);
+#else
+  u3z(ovo); u3z(gon);
+#endif
 }
 
 /* _sist_sing(): replay ovum from the past, time already set.

From 9bfc5674c32d787ce777ad766d7ea5c64f5888a2 Mon Sep 17 00:00:00 2001
From: "C. Guy Yarvin" <cgyarvin@gmail.com>
Date: Tue, 19 May 2015 17:04:08 -0700
Subject: [PATCH 09/12] Enable -q.

---
 i/n/o.h    | 3 ++-
 i/v/vere.h | 1 +
 n/n.c      | 8 +++++---
 v/main.c   | 9 ++++++++-
 4 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/i/n/o.h b/i/n/o.h
index 7b90e9b27..8591dfee3 100644
--- a/i/n/o.h
+++ b/i/n/o.h
@@ -23,7 +23,8 @@
         u3o_check_corrupt = 0x4,              //  check: gc memory
         u3o_check_fatal =   0x8,              //  check: unrecoverable
         u3o_verbose =       0x10,             //  be remarkably wordy
-        u3o_dryrun =        0x20              //  don't touch checkpoint
+        u3o_dryrun =        0x20,             //  don't touch checkpoint
+        u3o_quiet =         0x40              //  disable ~&
       };
 
   /** Globals.
diff --git a/i/v/vere.h b/i/v/vere.h
index 6f50c2863..05f89d2c4 100644
--- a/i/v/vere.h
+++ b/i/v/vere.h
@@ -538,6 +538,7 @@
         c3_o    pro;                        //  -P, profile
         c3_o    veb;                        //  -v, verbose (inverse of -q)
         c3_o    nuu;                        //  -c, new pier
+        c3_o    qui;                        //  -q, quiet
         c3_o    vno;                        //  -V, turn on +verb
         c3_o    mem;                        //  -M, memory madness
       } u3_opts;
diff --git a/n/n.c b/n/n.c
index 61af0fd41..a41c7634e 100644
--- a/n/n.c
+++ b/n/n.c
@@ -46,9 +46,11 @@ _n_hint(u3_noun zep,
     }
 
     case c3__slog: {
-      u3t_off(noc_o);
-      u3t_slog(hod);
-      u3t_on(noc_o);
+      if ( !(u3C.wag_w & u3o_quiet) ) {
+        u3t_off(noc_o);
+        u3t_slog(hod);
+        u3t_on(noc_o);
+      }
       return _n_nock_on(bus, nex);
     }
 
diff --git a/v/main.c b/v/main.c
index d1163ec06..15fea5f82 100644
--- a/v/main.c
+++ b/v/main.c
@@ -74,6 +74,7 @@ _main_getopt(c3_i argc, c3_c** argv)
   u3_Host.ops_u.pro = c3n;
   u3_Host.ops_u.dry = c3n;
   u3_Host.ops_u.veb = c3n;
+  u3_Host.ops_u.qui = c3n;
   u3_Host.ops_u.nuu = c3n;
   u3_Host.ops_u.mem = c3n;
   u3_Host.ops_u.kno_w = DefaultKernel;
@@ -144,7 +145,7 @@ _main_getopt(c3_i argc, c3_c** argv)
       case 'g': { u3_Host.ops_u.gab = c3y; break; }
       case 'P': { u3_Host.ops_u.pro = c3y; break; }
       case 'D': { u3_Host.ops_u.dry = c3y; break; }
-      case 'q': { u3_Host.ops_u.veb = c3n; break; }
+      case 'q': { u3_Host.ops_u.qui = c3y; break; }
       case 'v': { u3_Host.ops_u.veb = c3y; break; }
       case '?': default: {
         return c3n;
@@ -350,6 +351,12 @@ main(c3_i   argc,
       if ( _(u3_Host.ops_u.veb) ) {
         u3C.wag_w |= u3o_verbose;
       }
+
+      /*  Set quiet flag.
+      */
+      if ( _(u3_Host.ops_u.qui) ) {
+        u3C.wag_w |= u3o_quiet;
+      }
       
       /*  Set dry-run flag.
       */

From 8964da0c8bbea9b665ae124a89abe6d4efcab4bc Mon Sep 17 00:00:00 2001
From: "C. Guy Yarvin" <cgyarvin@gmail.com>
Date: Tue, 19 May 2015 19:38:03 -0700
Subject: [PATCH 10/12] Check in demo instructions.

---
 demo/commands.txt                  | 127 ++++++++++++++++++++
 demo/files/1-ape-tictactoe.hoon    | 123 +++++++++++++++++++
 demo/files/2-ape-tictactoe.hoon    | 174 +++++++++++++++++++++++++++
 demo/files/3-ape-tictactoe.hoon    | 185 +++++++++++++++++++++++++++++
 demo/files/mar-tictactoe-game.hoon |  26 ++++
 demo/files/mar-tictactoe-move.hoon |  16 +++
 demo/files/pub-tictactoe-hymn.hoon |  32 +++++
 demo/files/pub-tictactoe-main.css  | 102 ++++++++++++++++
 demo/files/pub-tictactoe-main.js   |  62 ++++++++++
 demo/install1.sh                   |   9 ++
 demo/install2.sh                   |  12 ++
 demo/install3.sh                   |  21 ++++
 demo/script-1.txt                  |  27 +++++
 demo/script-2.txt                  | 147 +++++++++++++++++++++++
 14 files changed, 1063 insertions(+)
 create mode 100644 demo/commands.txt
 create mode 100644 demo/files/1-ape-tictactoe.hoon
 create mode 100644 demo/files/2-ape-tictactoe.hoon
 create mode 100644 demo/files/3-ape-tictactoe.hoon
 create mode 100644 demo/files/mar-tictactoe-game.hoon
 create mode 100644 demo/files/mar-tictactoe-move.hoon
 create mode 100644 demo/files/pub-tictactoe-hymn.hoon
 create mode 100644 demo/files/pub-tictactoe-main.css
 create mode 100644 demo/files/pub-tictactoe-main.js
 create mode 100755 demo/install1.sh
 create mode 100755 demo/install2.sh
 create mode 100755 demo/install3.sh
 create mode 100644 demo/script-1.txt
 create mode 100644 demo/script-2.txt

diff --git a/demo/commands.txt b/demo/commands.txt
new file mode 100644
index 000000000..2d7987cf0
--- /dev/null
+++ b/demo/commands.txt
@@ -0,0 +1,127 @@
+
+Commands 
+
+[from URL bar]
+  ***TBD - Galen/Anton please fill in
+
+[from unix]
+  For A, to build and boot:
+      git clone https://github.com/urbit/urbit
+      cd urbit
+      make
+      bin/urbit -T $A -c $A
+
+  For A, to kill and restart from checkpoint:
+      [in new terminal] killall -9 urbit
+      [in old terminal] urbit $A
+
+  For A, to kill, delete checkpoint, and rerun events:
+      [in new terminal] killall -9 urbit; rm -rf $A/.urb/chk
+      [in old terminal] urbit $A
+
+  For B, to edit /foo/bar/hoon:
+      *** Philip/anyone, add directions to install vim style
+
+      vim urbit/$B/$B/in/$DEMO/foo/bar.hoon
+
+
+[from talk]
+  For A, to private-message B (who defaults to talking back):
+
+      ;~HER
+
+  To create a channel '%foobar':
+
+      ;create channel %foobar 'channel description'
+
+[from hood, #]
+
+  For A or B, to start tictactoe:
+
+      *demo/tictactoe
+
+[from dojo]
+
+  For B, to create a %demo desk for this project:
+
+      :+merge %demo ~B %home
+
+  For A, to sync and follow B's demo desk:
+
+      :+sync %demo ~B %demo
+
+  *** - put bitcoin instructions here
+
+
+[files in script, clay and unix]
+
+    The tictactoe app, all three versions:
+
+        /=demo=/ape/tictactoe/core/hook
+        urbit/$X/$X/in/$DEMO/ape/tictactoe/core/hook
+        
+        version 1 (centralized):
+          $DEMO/files/1-ape-tictactoe.hoon
+        
+        version 2 (distributed):
+          $DEMO/files/2-ape-tictactoe.hoon
+
+        version 3 (webified)
+          $DEMO/files/3-ape-tictactoe.hoon
+
+  Helper files needed for version 2:
+  
+    The %tictactoe-game mark, for game update diffs:
+
+        /=demo=/mar/tictactoe-game/door/hook
+        urbit/$X/$X/in/$DEMO/mar/tictactoe-game/door.hook
+        $DEMO/files/mar-tictactoe-game.hoon 
+   
+  Helper files needed for version 3:
+
+    The %tictactoe-move mark, for moves from the web:
+
+        /=demo=/mar/tictactoe-move/door/hook
+        urbit/$X/$X/in/$DEMO/mar/tictactoe-move/door.hook
+        $DEMO/files/mar-tictactoe-move.hoon 
+ 
+    The HTML generator:
+    
+        /=demo=/pub/tictactoe/fab/hymn/hook
+        urbit/$X/$X/in/$DEMO/pub/tictactoe/fab/hymn.hook
+        $DEMO/files/pub-tictactoe-hymn.hoon
+
+    The CSS:
+
+        /=demo=/pub/tictactoe/src/main/css
+        urbit/$X/$X/in/$DEMO/pub/tictactoe/src/main.css
+        $DEMO/files/pub-tictactoe-main.css
+
+    The JS:
+
+        /=demo=/pub/tictactoe/src/main/js
+        urbit/$X/$X/in/$DEMO/pub/tictactoe/src/main.js
+        $DEMO/files/pub-tictactoe-main.js
+
+[from tictactoe]
+  
+  To move: 
+  
+      X/Y where X is row, Y is column.
+
+  To connect to a remote server (in versions 2 and 3),
+  specifying the side you will play:
+
+      ~X x
+      ~X o
+ 
+  To disconnect from a remote server (versions 2 and 3)
+
+      ~   *** - not well tested
+
+[scripts, to run from branch root directory]
+
+    $DEMO/install1.sh - copy in all version 1 (centralized) files
+    $DEMO/install2.sh - copy in all version 2 (distributed) files
+    $DEMO/install3.sh - copy in all version 3 (webby) files
+
diff --git a/demo/files/1-ape-tictactoe.hoon b/demo/files/1-ape-tictactoe.hoon
new file mode 100644
index 000000000..a22146447
--- /dev/null
+++ b/demo/files/1-ape-tictactoe.hoon
@@ -0,0 +1,123 @@
+::                                                      ::  ::
+::::  /hook/core/acto/ape                               ::  ::  dependencies
+  ::                                                    ::  ::
+/-  *sole                                               ::  structure
+/+  sole                                                ::  library
+::                                                      ::  ::
+::::                                                    ::  ::  structures
+  !:                                                    ::  ::
+=>  |%                                                  ::  board logic
+    ++  board  ,@                                       ::  one-player bitfield
+    ++  point  ,[x=@ y=@]                               ::  coordinate
+    ++  game   ,[who=? box=board boo=board]             ::  game state
+    ++  icon   |=(? ?:(+< 'X' 'O'))                     ::  display at
+    ++  bo                                              ::  per board
+      |_  bud=board                                     ::
+      ++  get  |=(point =(1 (cut 0 [(off +<) 1] bud)))  ::  get point
+      ++  off  |=(point (add x (mul 3 y)))              ::  bitfield address
+      ++  set  |=(point (con bud (bex (off +<))))       ::  set point
+      ++  win  %-  lien  :_  |=(a=@ =(a (dis a bud)))   ::  test for win
+               (rip 4 0wl04h0.4A0Aw.4A00s.0e070)        ::
+      --                                                ::
+    ::                                                  ::  ::
+    ::::                                                ::  ::  semantics
+      ::                                                ::  ::
+    ++  go                                              ::  per game
+      |_  game                                          ::
+      ++  at  |_  point                                 ::  per point
+              ++  g  +>+<                               ::  game
+              ++  k  !|(x o)                            ::  ok move
+              ++  m  ?.(k [| g] [& g:t:?:(who y p)])    ::  move
+              ++  o  (~(get bo boo) +<)                 ::  old at o
+              ++  p  .(boo (~(set bo boo) +<))          ::  play at o
+              ++  t  .(who !who)                        ::  take turn
+              ++  v  ?:(x (icon &) ?:(o (icon |) '.'))  ::  view
+              ++  x  (~(get bo box) +<)                 ::  old at x
+              ++  y  .(box (~(set bo box) +<))          ::  play at x
+              --                                        ::
+      ++  res  ?:  ~(win bo box)  `"{~[(icon &)]} wins" ::  result
+               ?:  ~(win bo boo)  `"{~[(icon |)]} wins" ::
+               ?:  =(511 (con boo box))  `"tie :-("  ~  ::
+      ++  row  |=  y=@   :~  (add y '1')                ::  print row
+                   ' '  ~(v at y 0)                     ::
+                   ' '  ~(v at y 1)                     ::
+                   ' '  ~(v at y 2)                     ::
+               ==                                       ::
+      ++  tab  ~["+ 1 2 3" (row 0) (row 1) (row 2)]     ::  print table
+      --                                                ::
+    --                                                  ::
+::                                                      ::  ::
+::::                                                    ::  ::  server
+  ::                                                    ::  ::
+=>  |%                                                  ::  arvo structures
+    ++  axle  ,[%0 eye=face gam=game]                   ::  agent state
+    ++  card  ,[%diff lime]                             ::  update
+    ++  face  (pair (list ,@c) (map bone sole-share))   ::  interface
+    ++  lime  ,[%sole-effect sole-effect]               ::  console update
+    ++  move  (pair bone card)                          ::  cause and action
+    --                                                  ::
+=>  |%                                                  ::  parsers
+    ++  colm  (cook |=(a=@ (sub a '1')) (shim '1' '3')) ::  row or column
+    ++  come  ;~(plug colm ;~(pfix fas colm))           ::  coordinate
+    --                                                  ::
+|_  [hid=hide moz=(list move) axle]                     ::  per agent
+++  et                                                  ::
+  |_  [from say=sole-share]                             ::  per console
+  ++  abet  +>(q.eye (~(put by q.eye) ost say))         ::  continue
+  ++  amok  +>(q.eye (~(del by q.eye) ost))             ::  discontinue
+  ++  beep  (emit %bel ~)                               ::  bad user
+  ++  delt  |=  cal=sole-change                         ::  input line change
+            =^  cul  say  (remit:sole cal good)         ::
+            ?~  cul  (park:abet(p.eye buf.say) | ~)     ::
+            abet:beep:(emit det/u.cul)                  ::
+  ++  emit  |=  fec=sole-effect  ^+  +>                 ::  send effect
+            +>(moz [[ost %diff %sole-effect fec] moz])  ::  
+  ++  emil  |=  fex=(list sole-effect)                  ::  send effects
+            ?~(fex +> $(fex t.fex, +> (emit i.fex)))    ::
+  ++  good  |=((list ,@c) -:(rose (tufa +<) come))      ::  valid input
+  ++  kick  |=  point                                   ::  move command
+            =^  dud  gam  ~(m ~(at go gam) +<)          ::
+            ?.  dud  abet:beep  =+  mus=~(res go gam)   ::
+            (park:abet(gam ?^(mus *game gam)) %2 mus)   ::
+  ++  line  =^  cal  say  (transmit:sole set/p.eye)     ::  update command
+            (emit %det cal)                             ::
+  ++  make  =+  dur=(rust (tufa p.eye) come)            ::
+            ?~  dur  abet:beep                          ::
+            (kick:line(p.eye ~) +.dur)                  ::
+  ++  mean  |=((unit tape) ?~(+< +> (emit txt/+<+)))    ::  optional message
+  ++  play  |=  lev=?(%0 %1 %2)                         ::  update by level
+            ?-(lev %0 +>, %1 line, %2 line:show:prom)   ::
+  ++  plow  |=  [lev=?(%0 %1 %2) mus=(unit tape)]       ::  complete print
+            abet:(mean:(play lev) mus)                  ::
+  ++  prom  %^  emit  %pro  %&  :-  %acto               ::  update prompt
+            ": {~[(icon who.gam)]} to move (row/col): " ::  
+  ++  rend  (turn `wall`~(tab go gam) |=(tape txt/+<))  ::  table print
+  ++  show  (emit %mor rend)                            ::  update board
+  ++  sole  ~(. cs say)                                 ::  console library
+  ++  work  |=  act=sole-action                         ::  console input
+            ?:(?=(%det -.act) (delt +.act) make)        ::
+  --                                                    ::
+++  abet  [(flop moz) .(moz ~)]                         ::  resolve core
+++  flet  |=(from ~(. et +< (~(got by q.eye) ost)))     ::  in old client
+++  fret  |=(from ~(. et +< *sole-share))               ::  in new client
+++  pals  %+  turn  (pale hid (prix /sole))  |=  sink   ::  per console 
+          [[p=p.+< q=q.+<] r=(~(got by q.eye) p.+<)]    ::
+++  park  |=  [lev=?(%0 %1 %2) mus=(unit tape)]         ::  general update
+          =+  pals  |-  ^+  +>.^$  ?~  +<  +>.^$        ::
+          $(+< t.+<, +>.^$ (~(plow et i.+<) lev mus))   ::
+::                                                      ::  ::
+::::                                                    ::  ::  events
+  ::                                                    ::  ::
+++  peer-sole                                           ::  console subscribe
+          |=  [from *]  =<  abet                        ::
+          (plow:(fret +<-) %2 ~)                        ::
+++  poke-sole-action                                    ::  console input
+          |=  [from act=sole-action]  =<  abet          ::
+          (work:(flet +<-) act)                         ::
+++  prep  |=  [from old=(unit ,[(list move) axle])]     ::  initialize
+          =<  abet  ?~  old  +>  =<  (park %2 ~)        ::
+          +>(+<+ u.old)                                 ::
+++  pull-sole                                           ::  disconnect console
+          |=  [from *]  =<  abet                        ::
+          amok:(flet +<-)                               ::
+--
diff --git a/demo/files/2-ape-tictactoe.hoon b/demo/files/2-ape-tictactoe.hoon
new file mode 100644
index 000000000..34779285c
--- /dev/null
+++ b/demo/files/2-ape-tictactoe.hoon
@@ -0,0 +1,174 @@
+::                                                      ::  ::
+::::  /hook/core/acto/ape                               ::  ::  dependencies
+  ::                                                    ::  ::
+/-  *sole                                               ::  structures
+/+  sole                                                ::  libraries
+::                                                      ::  ::
+::::                                                    ::  ::  structures
+  !:                                                    ::  ::
+=>  |%                                                  ::  board logic
+    ++  board  ,@                                       ::  one-player bitfield
+    ++  point  ,[x=@ y=@]                               ::  coordinate
+    ++  game   ,[who=? box=board boo=board]             ::  game state
+    ++  icon   |=(? ?:(+< 'X' 'O'))                     ::  display at
+    ++  bo                                              ::  per board
+      |_  bud=board                                     ::
+      ++  get  |=(point =(1 (cut 0 [(off +<) 1] bud)))  ::  get point
+      ++  off  |=(point (add x (mul 3 y)))              ::  bitfield address
+      ++  set  |=(point (con bud (bex (off +<))))       ::  set point
+      ++  win  %-  lien  :_  |=(a=@ =(a (dis a bud)))   ::  test for win
+               (rip 4 0wl04h0.4A0Aw.4A00s.0e070)        ::  with bitmasks
+      --                                                ::
+    ++  go                                              ::  per game
+      |_  game                                          ::
+      ++  at  |_  point                                 ::  per point
+              ++  g  +>+<                               ::  game
+              ++  k  !|(x o)                            ::  ok move
+              ++  m  ?.(k [| g] [& g:t:?:(who y p)])    ::  move
+              ++  o  (~(get bo boo) +<)                 ::  old at o
+              ++  p  .(boo (~(set bo boo) +<))          ::  play at o
+              ++  t  .(who !who)                        ::  take turn
+              ++  v  ?:(x (icon &) ?:(o (icon |) '.'))  ::  view
+              ++  x  (~(get bo box) +<)                 ::  old at x
+              ++  y  .(box (~(set bo box) +<))          ::  play at x
+              --                                        ::
+      ++  res  ?:  ~(win bo box)  `"{~[(icon &)]} wins" ::  result
+               ?:  ~(win bo boo)  `"{~[(icon |)]} wins" ::
+               ?:  =(511 (con boo box))  `"tie :-("  ~  ::
+      ++  row  |=  y=@   :~  (add y '1')                ::  print row
+                   ' '  ~(v at y 0)                     ::
+                   ' '  ~(v at y 1)                     ::
+                   ' '  ~(v at y 2)                     ::
+               ==                                       ::
+      ++  tab  ~["+ 1 2 3" (row 0) (row 1) (row 2)]     ::  print table
+      --                                                ::
+    --                                                  ::
+::                                                      ::  ::
+::::                                                    ::  ::  server
+  ::                                                    ::  ::
+=>  |%                                                  ::  arvo structures
+    ++  axle  ,[%1 eye=face but=tube gam=game]          ::  agent state
+    ++  axon  $?(axle [%0 eye=face gam=game])           ::  historical state
+    ++  card  $%  [%diff lime]                          ::  update
+                  [%quit ~]                             ::  cancel
+                  [%peer wire dock path]                ::  subscribe
+                  [%pull wire dock ~]
+              ==                                        ::
+    ++  face  (pair (list ,@c) (map bone sole-share))   ::  interface
+    ++  lime  $%  [%sole-effect sole-effect]            ::  :sole update
+                  [%octo-game game]                     ::  :octo update
+              ==                                        ::
+    ++  move  (pair bone card)                          ::  cause and action
+    ++  mote  (pair ship ,?)                            ::  remote binding
+    ++  tube  (unit (pair ,? mote))                     ::  alive, remote
+    --                                                  ::
+=>  |%                                                  ::  parsers
+    ++  colm  (cook |=(a=@ (sub a '1')) (shim '1' '3')) ::  row or column
+    ++  come  ;~(plug colm ;~(pfix fas colm))           ::  coordinate
+    ++  comb  (pick come ;~(pfix sig (punt comp)))      ::  all command input
+    ++  comp  ;~(plug fed:ag ;~(pfix ace (flag %x %o))) ::  login command
+    ++  cope  |=(? ?:(+< (stag %| (cold ~ sig)) comb))  ::  with wait mode
+    --                                                  ::
+|_  [hid=hide moz=(list move) axle]                     ::  per agent
+++  et                                                  ::
+  |_  [from say=sole-share]                             ::  per console client
+  ++  abet  +>(q.eye (~(put by q.eye) ost say))         ::  continue
+  ++  amok  +>(q.eye (~(del by q.eye) ost))             ::  discontinue
+  ++  beep  (emit %bel ~)                               ::  bad user
+  ++  cusp  (cope wait)                                 ::  parsing rule
+  ++  delt  |=  cal=sole-change                         ::  input line change
+            =^  cul  say  (remit:sole cal good)         ::
+            ?~  cul  (park:abet(p.eye buf.say) | ~)     ::
+            abet:beep:(emit det/u.cul)                  ::
+  ++  emit  |=  fec=sole-effect  ^+  +>                 ::  send effect
+            +>(moz [[ost %diff %sole-effect fec] moz])  ::  
+  ++  emil  |=  fex=(list sole-effect)                  ::  send effects
+            ?~(fex +> $(fex t.fex, +> (emit i.fex)))    ::
+  ++  good  |=((list ,@c) -:(rose (tufa +<) cusp))      ::  valid input
+  ++  kick  |=  point                                   ::  move command
+            =^  dud  gam  ~(m ~(at go gam) +<)          ::
+            ?.  dud  abet:beep  =+  mus=~(res go gam)   ::
+            (park:abet(gam ?^(mus *game gam)) %2 mus)   ::
+  ++  line  =^  cal  say  (transmit:sole set/p.eye)     ::  update command
+            (emit %det cal)                             ::
+  ++  make  =+  dur=(rust (tufa p.eye) comb)            ::
+            ?~  dur  abet:beep                          ::
+            =.  +  line(p.eye ~)                        ::
+            ?-(+<.dur & (kick +>.dur), | (plan +>.dur)) ::
+  ++  mean  |=((unit tape) ?~(+< +> (emit txt/+<+)))    ::  optional message
+  ++  play  |=  lev=?(%0 %1 %2)                         ::  update by level
+            ?-(lev %0 +>, %1 line, %2 line:show:prom)   ::
+  ++  plow  |=  [lev=?(%0 %1 %2) mus=(unit tape)]       ::  complete print
+            abet:(mean:(play lev) mus)                  ::
+  ++  prom  %^  emit  %pro  %&  :-  %octo               ::  update prompt
+            ?:  wait  "(their turn) "                   ::
+            ": {~[(icon who.gam)]} to move (row/col): " ::  
+  ++  plan  |=  mut=(unit mote)                         ::  peer command
+            ?~  mut  ?~(but abet:beep stop:abet)        ::
+            ?^(but abet:beep (link:abet u.mut))         ::
+  ++  rend  (turn `wall`~(tab go gam) |=(tape txt/+<))  ::  table print
+  ++  show  (emit %mor rend)                            ::  update board
+  ++  sole  ~(. cs say)                                 ::  console library
+  ++  wait  &(?=(^ but) !=(q.q.u.but who.gam))          ::  waiting turn
+  ++  work  |=  act=sole-action                         ::  console input
+            ?:(?=(%det -.act) (delt +.act) make)        ::
+  --                                                    ::
+++  abet  [(flop moz) .(moz ~)]                         ::  resolve core
+++  dump  |=(mov=move %_(+> moz [mov moz]))             ::  send move
+++  dish  |=(cad=card (dump 0 cad))                     ::  forward move
+++  flet  |=(from ~(. et +< (~(got by q.eye) ost)))     ::  in old client
+++  fret  |=(from ~(. et +< *sole-share))               ::  in new client
+++  like  |=(xir=ship |*(* [/octo [xir %octo] +<]))     ::  to friend
+++  link  |=  mot=mote  %+  dish(but `[| mot])  %peer   ::  subscribe to friend
+          ((like p.mot) /octo/net/[?:(q.mot %x %o)])    ::  
+++  pals  %+  turn  (pale hid (prix /sole))  |=  sink   ::  per console 
+          [[p=p.+< q=q.+<] r=(~(got by q.eye) p.+<)]    ::
+++  park  |=  [lev=?(%0 %1 %2) mus=(unit tape)]         ::  update all
+          =.  +>  ?:(=(%2 lev) push +>)                 ::  
+          =+  pals                                      ::
+          |-  ^+  +>.^$  ?~  +<  +>.^$                  ::
+          $(+< t.+<, +>.^$ (~(plow et i.+<) lev mus))   ::
+++  push  =+  pey=(pale hid (prix /octo))  |-  ^+  +>   ::  update friends
+          ?~(pey +> $(pey t.pey, +> (sell p.i.pey)))    ::
+++  sell  |=(ost=bone (dump ost %diff %octo-game gam))  ::  update friend
+++  stop  (dish(but ~) pull/((like +>-.but) ~))         ::  cancel subscribe
+::                                                      :::::::::::::::
+::::                                                    ::  ::       ::  hooks
+  ::                                                    :::::::::::::::
+++  diff-octo-game                                      ::  friend update
+          |=  [then gam=game]  =<  abet                 ::
+          ?.  &(?=([~ %& *] but) =(src p.q.u.but))  +>  ::
+          ?:  =(^gam gam)  +>                           ::
+          (park(gam gam) %2 ~)                          ::
+++  peer-octo-net                                       ::  urbit peer
+          |=  [from pax=path]  =<  abet                 ::
+          =+  who==(%x -.pax)                           ::
+          ?^  but  (park %2 ~)                          ::
+          (park:(link src !who) %2 `"net from {<src>}") ::
+++  peer-sole                                           ::  console subscribe
+          |=  [from pax=path]  =<  abet                 ::
+          (plow:(fret +<-) %2 ~)                        ::
+++  poke-sole-action                                    ::  console input
+          |=  [from act=sole-action]  =<  abet          ::
+          (work:(flet +<-) act)                         ::
+++  prep  |=  [from old=(unit ,[(list move) axon])]     ::  initialize
+          =<  abet  ?~  old  +>                         ::
+          =<  (park %2 ~)                               ::
+          ?-  -.+>.old                                  ::
+            %1  +>(+<+ u.old)                           ::
+            %0  +>(eye.+< eye.+>.old, gam.+< gam.+>.old)::
+          ==                                            ::
+++  pull-octo                                           ::
+          |=  [from *]  =<  abet                        ::
+          (park(but ~) %2 `"dropped")                   ::
+++  pull-sole                                           ::  disconnect console
+          |=  [from *]  =<  abet                        ::
+          amok:(flet +<-)                               ::
+++  quit-octo                                           ::  unlinked by friend
+          |=([then ~] abet:(park(but ~) %0 `"removed")) ::
+++  reap-octo                                           ::  linked to friend
+          |=  [then saw=(unit tang)]  =<  abet          ::
+          ?>  ?=([~ %| *] but)                          ::
+          ?^  saw  (park:stop %0 `"fail to {<src>}")    ::
+          (park(p.u.but %&) %0 `"link to {<src>}")      ::
+--
diff --git a/demo/files/3-ape-tictactoe.hoon b/demo/files/3-ape-tictactoe.hoon
new file mode 100644
index 000000000..009f8c41d
--- /dev/null
+++ b/demo/files/3-ape-tictactoe.hoon
@@ -0,0 +1,185 @@
+::                                                      ::  ::
+::::  /hook/core/acto/ape                               ::  ::  dependencies
+  ::                                                    ::  ::
+/-  *sole                                               ::  structures
+/+  sole                                                ::  libraries
+::                                                      ::  ::
+::::                                                    ::  ::  structures
+  !:                                                    ::  ::
+=>  |%                                                  ::  board logic
+    ++  board  ,@                                       ::  one-player bitfield
+    ++  point  ,[x=@ y=@]                               ::  coordinate
+    ++  game   ,[who=? box=board boo=board]             ::  game state
+    ++  icon   |=(? ?:(+< 'X' 'O'))                     ::  display at
+    ++  bo                                              ::  per board
+      |_  bud=board                                     ::
+      ++  get  |=(point =(1 (cut 0 [(off +<) 1] bud)))  ::  get point
+      ++  off  |=(point (add x (mul 3 y)))              ::  bitfield address
+      ++  set  |=(point (con bud (bex (off +<))))       ::  set point
+      ++  win  %-  lien  :_  |=(a=@ =(a (dis a bud)))   ::  test for win
+               (rip 4 0wl04h0.4A0Aw.4A00s.0e070)        ::  with bitmasks
+      --                                                ::
+    ++  go                                              ::  per game
+      |_  game                                          ::
+      ++  at  |_  point                                 ::  per point
+              ++  g  +>+<                               ::  game
+              ++  k  !|(x o)                            ::  ok move
+              ++  m  ?.(k [| g] [& g:t:?:(who y p)])    ::  move
+              ++  o  (~(get bo boo) +<)                 ::  old at o
+              ++  p  .(boo (~(set bo boo) +<))          ::  play at o
+              ++  t  .(who !who)                        ::  take turn
+              ++  v  ?:(x (icon &) ?:(o (icon |) '.'))  ::  view
+              ++  x  (~(get bo box) +<)                 ::  old at x
+              ++  y  .(box (~(set bo box) +<))          ::  play at x
+              --                                        ::
+      ++  res  ?:  ~(win bo box)  `"{~[(icon &)]} wins" ::  result
+               ?:  ~(win bo boo)  `"{~[(icon |)]} wins" ::
+               ?:  =(511 (con boo box))  `"tie :-("  ~  ::
+      ++  row  |=  y=@   :~  (add y '1')                ::  print row
+                   ' '  ~(v at y 0)                     ::
+                   ' '  ~(v at y 1)                     ::
+                   ' '  ~(v at y 2)                     ::
+               ==                                       ::
+      ++  tab  ~["+ 1 2 3" (row 0) (row 1) (row 2)]     ::  print table
+      --                                                ::
+    --                                                  ::
+::                                                      ::  ::
+::::                                                    ::  ::  server
+  ::                                                    ::  ::
+=>  |%                                                  ::  arvo structures
+    ++  axle  ,[%1 eye=face but=tube gam=game]          ::  agent state
+    ++  axon  $?(axle [%0 eye=face gam=game])           ::  historical state
+    ++  card  $%  [%diff lime]                          ::  update
+                  [%quit ~]                             ::  cancel
+                  [%peer wire dock path]                ::  subscribe
+                  [%pull wire dock ~]
+              ==                                        ::
+    ++  face  (pair (list ,@c) (map bone sole-share))   ::  interface
+    ++  lime  $%  [%sole-effect sole-effect]            ::  :sole update
+                  [%octo-game game]                     ::  :octo update
+              ==                                        ::
+    ++  move  (pair bone card)                          ::  cause and action
+    ++  mote  (pair ship ,?)                            ::  remote binding
+    ++  tube  (unit (pair ,? mote))                     ::  alive, remote
+    --                                                  ::
+=>  |%                                                  ::  parsers
+    ++  colm  (cook |=(a=@ (sub a '1')) (shim '1' '3')) ::  row or column
+    ++  come  ;~(plug colm ;~(pfix fas colm))           ::  coordinate
+    ++  comb  (pick come ;~(pfix sig (punt comp)))      ::  all command input
+    ++  comp  ;~(plug fed:ag ;~(pfix ace (flag %x %o))) ::  login command
+    ++  cope  |=(? ?:(+< (stag %| (cold ~ sig)) comb))  ::  with wait mode
+    --                                                  ::
+|_  [hid=hide moz=(list move) axle]                     ::  per agent
+++  et                                                  ::
+  |_  [from say=sole-share]                             ::  per console client
+  ++  abet  +>(q.eye (~(put by q.eye) ost say))         ::  continue
+  ++  amok  +>(q.eye (~(del by q.eye) ost))             ::  discontinue
+  ++  beep  (emit %bel ~)                               ::  bad user
+  ++  cusp  (cope wait)                                 ::  parsing rule
+  ++  delt  |=  cal=sole-change                         ::  input line change
+            =^  cul  say  (remit:sole cal good)         ::
+            ?~  cul  (park:abet(p.eye buf.say) | ~)     ::
+            abet:beep:(emit det/u.cul)                  ::
+  ++  emit  |=  fec=sole-effect  ^+  +>                 ::  send effect
+            +>(moz [[ost %diff %sole-effect fec] moz])  ::  
+  ++  emil  |=  fex=(list sole-effect)                  ::  send effects
+            ?~(fex +> $(fex t.fex, +> (emit i.fex)))    ::
+  ++  good  |=((list ,@c) -:(rose (tufa +<) cusp))      ::  valid input
+  ++  kick  |=  point                                   ::  move command
+            =^  dud  gam  ~(m ~(at go gam) +<)          ::
+            ?.  dud  abet:beep  =+  mus=~(res go gam)   ::
+            (park:abet(gam ?^(mus *game gam)) %2 mus)   ::
+  ++  line  =^  cal  say  (transmit:sole set/p.eye)     ::  update command
+            (emit %det cal)                             ::
+  ++  make  =+  dur=(rust (tufa p.eye) comb)            ::
+            ?~  dur  abet:beep                          ::
+            =.  +  line(p.eye ~)                        ::
+            ?-(+<.dur & (kick +>.dur), | (plan +>.dur)) ::
+  ++  mean  |=((unit tape) ?~(+< +> (emit txt/+<+)))    ::  optional message
+  ++  play  |=  lev=?(%0 %1 %2)                         ::  update by level
+            ?-(lev %0 +>, %1 line, %2 line:show:prom)   ::
+  ++  plow  |=  [lev=?(%0 %1 %2) mus=(unit tape)]       ::  complete print
+            abet:(mean:(play lev) mus)                  ::
+  ++  prom  %^  emit  %pro  %&  :-  %octo               ::  update prompt
+            ?:  wait  "(their turn) "                   ::
+            ": {~[(icon who.gam)]} to move (row/col): " ::  
+  ++  plan  |=  mut=(unit mote)                         ::  peer command
+            ?~  mut  ?~(but abet:beep stop:abet)        ::
+            ?^(but abet:beep (link:abet u.mut))         ::
+  ++  rend  (turn `wall`~(tab go gam) |=(tape txt/+<))  ::  table print
+  ++  show  (emit %mor rend)                            ::  update board
+  ++  sole  ~(. cs say)                                 ::  console library
+  ++  wait  &(?=(^ but) !=(q.q.u.but who.gam))          ::  waiting turn
+  ++  work  |=  act=sole-action                         ::  console input
+            ?:(?=(%det -.act) (delt +.act) make)        ::
+  --                                                    ::
+++  abet  [(flop moz) .(moz ~)]                         ::  resolve core
+++  dump  |=(mov=move %_(+> moz [mov moz]))             ::  send move
+++  dish  |=(cad=card (dump 0 cad))                     ::  forward move
+++  flet  |=(from ~(. et +< (~(got by q.eye) ost)))     ::  in old client
+++  fret  |=(from ~(. et +< *sole-share))               ::  in new client
+++  like  |=(xir=ship |*(* [/octo [xir %octo] +<]))     ::  to friend
+++  link  |=  mot=mote  %+  dish(but `[| mot])  %peer   ::  subscribe to friend
+          ((like p.mot) /octo/net/[?:(q.mot %x %o)])    ::  
+++  pals  %+  turn  (pale hid (prix /sole))  |=  sink   ::  per console 
+          [[p=p.+< q=q.+<] r=(~(got by q.eye) p.+<)]    ::
+++  park  |=  [lev=?(%0 %1 %2) mus=(unit tape)]         ::  update all
+          =.  +>  ?:(=(%2 lev) push +>)                 ::  
+          =+  pals                                      ::
+          |-  ^+  +>.^$  ?~  +<  +>.^$                  ::
+          $(+< t.+<, +>.^$ (~(plow et i.+<) lev mus))   ::
+++  push  =+  pey=(pale hid (prix /octo))  |-  ^+  +>   ::  update friends
+          ?~(pey +> $(pey t.pey, +> (sell p.i.pey)))    ::
+++  sell  |=(ost=bone (dump ost %diff %octo-game gam))  ::  update friend
+++  stop  (dish(but ~) pull/((like +>-.but) ~))         ::  cancel subscribe
+::                                                      :::::::::::::::
+::::                                                    ::  ::       ::  hooks
+  ::                                                    :::::::::::::::
+++  diff-octo-game                                      ::  friend update
+          |=  [then gam=game]  =<  abet                 ::
+          ?.  &(?=([~ %& *] but) =(src p.q.u.but))  +>  ::
+          ?:  =(^gam gam)  +>                           ::
+          (park(gam gam) %2 ~)                          ::
+++  peer-octo-net                                       ::  urbit peer
+          |=  [from pax=path]  =<  abet                 ::
+          =+  who==(%x -.pax)                           ::
+          ?^  but  (park %2 ~)                          ::
+          (park:(link src !who) %2 `"net from {<src>}") ::
+++  peer-octo-web                                       ::  web peer
+          |=  [from pax=path]  =<  abet                 ::
+          ~&  [%peer-web +<]                            ::
+          ?^  but  (park %2 ~)                          ::
+          %+  park(but `[%& src !who.gam])  %2          ::
+          `"web from {<src>}"                           ::
+++  peer-sole                                           ::  console subscribe
+          |=  [from pax=path]  =<  abet                 ::
+          (plow:(fret +<-) %2 ~)                        ::
+++  poke-sole-action                                    ::  console input
+          |=  [from act=sole-action]  =<  abet          ::
+          (work:(flet +<-) act)                         ::
+++  poke-octo-move                                      ::
+          |=  [from wha=point]  =<  abet                ::
+          =^  dud  gam  ~(m ~(at go gam) wha)           ::
+          ?>  dud  =+  mus=~(res go gam)                ::
+          (park(gam ?^(mus *game gam)) %2 mus)          ::
+++  prep  |=  [from old=(unit ,[(list move) axon])]     ::  initialize
+          =<  abet  ?~  old  +>                         ::
+          =<  (park %2 ~)                               ::
+          ?-  -.+>.old                                  ::
+            %1  +>(+<+ u.old)                           ::
+            %0  +>(eye.+< eye.+>.old, gam.+< gam.+>.old)::
+          ==                                            ::
+++  pull-octo                                           ::
+          |=  [from *]  =<  abet                        ::
+          (park(but ~) %2 `"dropped")                   ::
+++  pull-sole                                           ::  disconnect console
+          |=  [from *]  =<  abet                        ::
+          amok:(flet +<-)                               ::
+++  quit-octo                                           ::  unlinked by friend
+          |=([then ~] abet:(park(but ~) %0 `"removed")) ::
+++  reap-octo                                           ::  linked to friend
+          |=  [then saw=(unit tang)]  =<  abet          ::
+          ?>  ?=([~ %| *] but)                          ::
+          ?^  saw  (park:stop %0 `"fail to {<src>}")    ::
+          (park(p.u.but %&) %0 `"link to {<src>}")      ::
+--
diff --git a/demo/files/mar-tictactoe-game.hoon b/demo/files/mar-tictactoe-game.hoon
new file mode 100644
index 000000000..d776a3c4b
--- /dev/null
+++ b/demo/files/mar-tictactoe-game.hoon
@@ -0,0 +1,26 @@
+::
+::::  /hook/door/octo-game/mar
+  ::
+/?    310
+!:
+|%
+++  rip9
+  =+  b=0
+  |=  a=@  ^-  (list ,@A)
+  ?:  =(b 9)  ~
+  [(cut 0 [b 1] a) $(b +(b))]
+--
+!:
+|_  cod=[who=? box=@ boo=@]                             ::  game state
+::
+++  grab                                                ::  convert from
+  |%
+  ++  noun  ,[who=? box=@ boo=@]                        ::  clam from %noun
+  --
+++  grow
+  |%
+  ++  json  ^-  ^json
+    =>  |=(bor=@ `^json`a/(turn (rip9 bor) |=(a=@A [%b =(1 a)])))
+    (jobe who/s/?:(who.cod %x %o) box/(. box.cod) boo/(. boo.cod) ~)
+  --
+--
diff --git a/demo/files/mar-tictactoe-move.hoon b/demo/files/mar-tictactoe-move.hoon
new file mode 100644
index 000000000..ab13eee6b
--- /dev/null
+++ b/demo/files/mar-tictactoe-move.hoon
@@ -0,0 +1,16 @@
+::
+::::  /hook/door/octo-move/mar
+  ::
+/?    314
+!:
+::::
+  ::
+=+  point=,[x=@ y=@]
+|_  point
+::
+++  grab                                                ::  convert from
+  |%
+  ++  json  (corl need (at ni ni ~):jo)                 ::  reparse from %json
+  ++  noun  point                                       ::  clam from %noun
+  --
+--
diff --git a/demo/files/pub-tictactoe-hymn.hoon b/demo/files/pub-tictactoe-hymn.hoon
new file mode 100644
index 000000000..526b5f796
--- /dev/null
+++ b/demo/files/pub-tictactoe-hymn.hoon
@@ -0,0 +1,32 @@
+::
+::
+::::  /hook/hymn/fab/octo/pub/
+  ::
+^-  manx
+;html
+  ;head
+    ;meta(charset "utf-8");
+    ;script(type "text/javascript", src "//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.js");
+    ;script(type "text/javascript", src "/~/at/base/lib/urb.js");
+    ;link(type "text/css", rel "stylesheet", href "/home/lib/base.css");
+    ;link(type "text/css", rel "stylesheet", href "/home/pub/octo/src/main.css");
+    ;title: :octo
+  ==
+  ;body
+    ;div#what
+      ;div#ship
+        ;div.sig: ~
+        ;div.ship;
+        ;div.as;
+      ==
+      ;div#vs: vs
+      ;div#user
+        ;div.sig: ~
+        ;div.ship;
+        ;div.as;
+      ==
+    ==
+    ;div#bord;
+    ;script(type "text/javascript", src "/home/pub/octo/src/main.js");
+  ==
+==
diff --git a/demo/files/pub-tictactoe-main.css b/demo/files/pub-tictactoe-main.css
new file mode 100644
index 000000000..5ea0da7bc
--- /dev/null
+++ b/demo/files/pub-tictactoe-main.css
@@ -0,0 +1,102 @@
+#what,
+#bord {
+  width: 600px;
+  text-align: center;
+  position: absolute;
+  left: 50%;
+  margin-left: -300px;
+}
+
+#what {
+  height: 36px;
+  top: 18px;
+}
+
+#bord {
+  height: 600px;
+  position: absolute;
+  top: 111px;
+  opacity: .6;
+}
+
+.turn #bord {
+  opacity: 1;
+}
+
+#what {
+  font-family: "bau";
+}
+
+#what div {
+  display: inline-block;
+}
+
+#what .ship {
+  font-weight: 400;
+  letter-spacing: 1px;
+  text-transform: uppercase;
+}
+
+.turn #what #ship,
+#what #user {
+  border: 2px solid #fff;
+}
+
+#what #ship,
+.turn #what #user {
+  border: 2px solid red;
+}
+
+#what #ship,
+#what #user {
+  padding: .6rem;
+}
+
+#what .as {
+  width: 1.6rem;
+}
+
+#vs {
+  margin: 0 1rem;
+  padding: .3rem;
+  color: #fff;
+  background-color: #000;
+}
+
+.spac {
+  font-size: 100px;
+  line-height: 200px;
+}
+
+.spac {
+  width: 198px;
+  height: 198px;
+  border: 1px solid #000;
+  text-align: center;
+  float: left;
+  cursor: pointer;
+}
+
+.spac[data-index="0-0"],
+.spac[data-index="1-0"],
+.spac[data-index="2-0"] {
+  border-left: 0;
+}
+
+.spac[data-index="0-0"],
+.spac[data-index="0-1"],
+.spac[data-index="0-2"] {
+  border-top: 0;
+}
+
+.spac[data-index="2-0"],
+.spac[data-index="2-1"],
+.spac[data-index="2-2"] {
+  border-bottom: 0;
+}
+
+.spac[data-index="0-2"],
+.spac[data-index="1-2"],
+.spac[data-index="2-2"] {
+  border-right: 0;
+}
diff --git a/demo/files/pub-tictactoe-main.js b/demo/files/pub-tictactoe-main.js
new file mode 100644
index 000000000..b3cc5d121
--- /dev/null
+++ b/demo/files/pub-tictactoe-main.js
@@ -0,0 +1,62 @@
+$(function() {
+  $bord = $('#bord')
+  $whom = $('#whom')
+
+  lett = ["x","o"]
+  symb = [" ","✕","◯"]
+  draw = function(state) {
+    space = function(_state,y,x) { 
+      return "<div class='spac' data-index='"+y+"-"+x+
+             "'>"+symb[_state]+"</div>" 
+      }
+    s = ""
+    x = 0
+    y = 0
+    for(i=0;i<9;i++) {
+      j = [0,3,6,1,4,7,2,5,8][i]  // XX math 
+      s += space((state.box[j] ? 1 : 0)+(state.boo[j] ? 2 : 0),y,x)
+      x++
+      if((i+1)%3 == 0) {
+        y++
+        x=0
+      }
+    }
+    $bord.html(s)
+   turn(state.who)
+  }
+
+  which = null
+  turn = function(who) {
+    $('body').toggleClass('turn',(who == which))
+  }
+
+  assign = function(who) {
+    which = who
+    turn(who)
+    $('#ship .as').text(symb[Number(!lett.indexOf(who))+1])
+    $('#user .as').text(symb[lett.indexOf(who)+1])
+  }
+
+  urb.appl = 'octo'
+  urb.bind('/octo/web', function(err,res) {
+    if(which == null) { assign(res.data.who) }
+    draw(res.data)
+  })
+
+  // draw({
+  //   box:[false,false,false,false,false,false,false,false,false],
+  //   boo:[false,false,false,false,false,false,false,false,false]
+  // })
+
+  $bord.on('click', function(e) {
+    if(!$('body').hasClass('turn')) { return false }
+    $t = $(e.target).closest('.spac')
+    data = $.map(
+      $t.attr('data-index').split('-'), 
+      function(i) { return Number(i); })
+    urb.send({mark:'octo-move',data:data})
+  })
+
+  $('#ship .ship').text(window.urb.ship)
+  $('#user .ship').text(window.urb.user)
+})
diff --git a/demo/install1.sh b/demo/install1.sh
new file mode 100755
index 000000000..41b08a1d5
--- /dev/null
+++ b/demo/install1.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+X=$1
+DEMO=demo
+COLD=$DEMO/files
+DESK=urbit/$X/$X/in/$DEMO
+
+echo "cp -f $COLD/1-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook"
+cp -f $COLD/1-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook
diff --git a/demo/install2.sh b/demo/install2.sh
new file mode 100755
index 000000000..6e3e0430b
--- /dev/null
+++ b/demo/install2.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+X=$1
+DEMO=demo
+COLD=$DEMO/files
+DESK=urbit/$X/$X/in/$DEMO
+
+echo "cp -f $COLD/2-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook"
+cp -f $COLD/1-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook
+
+echo "cp -f $COLD/mar-tictactoe-game.hoon $DESK/mar/tictactoe-game/door.hook"
+cp -f $COLD/mar-tictactoe-game.hoon $DESK/mar/tictactoe-game/door.hook
diff --git a/demo/install3.sh b/demo/install3.sh
new file mode 100755
index 000000000..261b846b7
--- /dev/null
+++ b/demo/install3.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+X=$1
+DEMO=demo
+COLD=$DEMO/files
+DESK=urbit/$X/$X/in/$DEMO
+
+echo "cp -f $COLD/3-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook"
+cp -f $COLD/3-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook
+
+echo "cp -f $COLD/mar-tictactoe-game.hoon $DESK/mar/tictactoe-game/door.hook"
+cp -f $COLD/mar-tictactoe-game.hoon $DESK/mar/tictactoe-game/door.hook
+
+echo "cp -f $COLD/pub-tictactoe-hymn.hoon $DESK/pub/tictactoe/fab/hymn.hook"
+cp -f $COLD/pub-tictactoe-hymn.hoon $DESK/pub/tictactoe/fab/hymn.hook
+
+echo "cp -f $COLD/pub-tictactoe-main.css $DESK/pub/tictactoe/src/main.css"
+cp -f $COLD/pub-tictactoe-main.css $DESK/pub/tictactoe/src/main.css
+
+echo "cp -f $COLD/pub-tictactoe-main.js $DESK/pub/tictactoe/src/main.js"
+cp -f $COLD/pub-tictactoe-main.js $DESK/pub/tictactoe/src/main.js
diff --git a/demo/script-1.txt b/demo/script-1.txt
new file mode 100644
index 000000000..fdd6cb633
--- /dev/null
+++ b/demo/script-1.txt
@@ -0,0 +1,27 @@
+script:
+  ~tasfyn-partyv and ~talsur-todres decide to build a tic-tac-toe game
+
+tasfyn-partyv: would you like to play a game of thermonuclear war?
+
+talsur-todres: no.  how about some tic-tac-toe?
+
+tasfyn-partyv: sure.  but wait, do we have a server?
+
+talsur-todres: 
+features of the game:
+  (0) we build one-computer two-player TTT 
+  (1) we build console tic-tac-toe 
+  (2) we install it over the network
+
+     + 1 2 3
+     1   X X
+     2 O   O
+     3 X O X
+
+     ? 1/3
+
+  (3) we update it to change the characters
+
+  (4) maybe cheating with some pretyped assets, we make a web view
+       
+  (5) 
diff --git a/demo/script-2.txt b/demo/script-2.txt
new file mode 100644
index 000000000..c6a1d5c38
--- /dev/null
+++ b/demo/script-2.txt
@@ -0,0 +1,147 @@
+A == ~tasfyn-partyv
+B == ~talsur-todres
+
+      A and B, on unix terminals on different machines, clone and
+      build urbit from scratch, cutting over the build.
+
+      Each screen is divided into two logical columns.  A's
+      screen is filled with two shells.  B's screen has a shell
+      on the left and is empty on the right.
+
+      At the unix prompt, both run
+
+        urbit -c myship
+
+      type in an invisible ticket, and begin their ships.  All
+      diagnostic messages are suppressed.  Both users land
+      initially in :talk.
+
+A: is this thing on?
+
+B: who am i?  why am i here?
+
+A: would you like to play a game of global thermonuclear war?
+
+B: wouldn't you prefer tic-tac-toe?
+
+A: sure, but i'll have to write it.  hang on...
+
+      A switches to :dojo and runs
+
+        :+merge %tic-tac-a ~tasfyn-partyv %home
+
+      In the other window, A runs vim and edits, occasionally
+      hitting :w to save the file:
+      
+      demo/file1.txt -> A/in/base/ape/tictactoe/core.hook
+
+      After ++bo,
+
+A: the board state is a bitfield
+
+A: btw, you can watch me code at <URL>.
+
+      B opens a browser and points it at <URL>, showing the 
+      tree with live update every time A saves.
+
+      After ++go:
+
+A: game semantics are not that complex...
+
+      After ++move:
+
+A: basic console io, kinda boilerplaty
+
+      After ++come:
+ 
+A: if you can infer the type of the product
+A: of a combinator parser, you are probably
+A: a typed functional language even if you
+A: leave category theory to the real math nerds... 
+
+      After ++park:
+
+A: a fairly vanilla console server.  probably some
+A: of this should be sucked out into a library - 
+A: you can never completely beat the boilerplate.
+A: also note that this is a two-way console with
+A: operational transformation that cancels syntax
+A: errors as you type, just like how :talk violates
+A: your human rights by lowercasing your capitals.
+A: finally, while the style is perfectly readable
+A: for a hoon programmer, we don't normally go in
+A: for this kind of mildly contrived topiary.
+ 
+      After ++pull-sole:
+
+A: those were the event hooks where arvo calls us,
+A: expecting a new state and a list of actions.
+A: anyway, this should work - let's try it.
+A: do this: 
+
+      :+sync %tic-tac-a ~tasfyn-partyv %tic-tac-a
+      :+start %tic-tac-a %tictactoe
+
+      B does this.  it puts him straight into TTT.
+
+A: now hang on, I'll join you.
+
+      A uses ^V to pop the hood and types +~B/
+
+A: bear in mind, this is a very crude shared space.
+A: your server is just exporting a console interface
+A: which we both can access.  so essentially i'm
+A: ssh-ed into your game world.
+
+      They play a couple of moves.
+
+A: it's important to note that your urbit is also
+A: in a sense, a database.  try this from unix:
+
+      killall -9 urbit
+      urbit myship
+
+      B does this, comes back and plays a move.
+
+B: we don't seem to have lost any data.
+A: we didn't even come close to losing data,
+A: so let's come a little closer:
+
+      killall -9 vere
+      rm -rf $checkpoint
+      urbit myship
+
+      B does this, comes back and plays a move.
+
+B: whoa, that was heavy.
+A: yeah, your life flashed before your eyes.  or at least,
+A: your event history.  this system of checkpoint
+A: and transaction log is actually how normal dbs work,
+A: though urbit is designed as a personal computer and
+A: hardly up for a normal db workload.
+
+B: it's a little odd that either of us could play X or O.
+A: or even have an edit war in the command line.
+
+      They have an edit war in the command line.
+
+B: it might be right for some things.  not tictactoe.
+A: then we'll have to change it!  often when someone
+A: installs your software, later you find out it's not
+A: perfect and sometimes actually needs to be changed.
+B: i've had that experience a number of times.
+A: but it's always tricky to operate on a beating heart,
+A: so let's try it in a small way first...
+
+      A edits the source file and changes X to Z, or
+      maybe to a Unicode symbol.  When he saves, the
+      change propagates to both consoles and also the
+      tree view on B's screen, even to the prompt UI.
+
+B: i've seen that sort of thing before.
+A: really?  in any case, let's do it for real.  the next
+A: version is a genuine distributed tictactoe with
+A: its own peer-to-peer move protocol.  surely this
+A: is some fancy technology...
+
+      A edits the source file into 

From 5b16f99726f812922023d03fc52d99e2324c0bf9 Mon Sep 17 00:00:00 2001
From: "C. Guy Yarvin" <cgyarvin@gmail.com>
Date: Tue, 19 May 2015 21:07:53 -0700
Subject: [PATCH 11/12] Latest greatest scriptest.

---
 demo/commands.txt |  10 ++-
 demo/script-3.txt | 163 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 172 insertions(+), 1 deletion(-)
 create mode 100644 demo/script-3.txt

diff --git a/demo/commands.txt b/demo/commands.txt
index 2d7987cf0..9dbe8213f 100644
--- a/demo/commands.txt
+++ b/demo/commands.txt
@@ -28,7 +28,7 @@ Commands
 [from talk]
   For A, to private-message B (who defaults to talking back):
 
-      ;~HER
+      ;~B
 
   To create a channel '%foobar':
 
@@ -40,6 +40,14 @@ Commands
 
       *demo/tictactoe
 
+  For A or B, to log in to X's tictactoe:
+
+      +~X/tictactoe
+
+  To log out:
+
+      -~X/tictactoe
+
 [from dojo]
 
   For B, to create a %demo desk for this project:
diff --git a/demo/script-3.txt b/demo/script-3.txt
new file mode 100644
index 000000000..70492e69c
--- /dev/null
+++ b/demo/script-3.txt
@@ -0,0 +1,163 @@
+For dialogue: start with dialogue ad-libbed by whoever is
+doing the production.  Later, copy it into a script and
+edit that script.
+
+For operation details, see commands.txt.  Fill in the script
+with literal operations *only once you have tested them
+yourself*.
+
+  A: build and boot A
+    
+    ...
+    ""
+
+  A: private-message B
+
+    ...
+    ""
+
+  B: create demo desk
+
+    ...
+    ""
+  
+  B: vim in application version 1, just typing, very fast
+
+    ...
+    ""
+
+  A: sync A's demo desk to B
+    
+    ...
+    ""
+
+  B: log in to A's tictactoe (intentionally reversed)
+    
+    ...
+    ""
+
+  A: start tictactoe on A
+
+  A/B: play ONE full game of tictactoe, moves interleaved with
+  these subdemos:
+
+    B changes X to Z in the source, then changes it back
+
+      ...
+      ""
+
+    A or B enters an invalid move, beep sound is heard
+
+      ...
+      ""
+
+    A kills and restarts the vere process:
+
+      ...
+      ""
+
+    A kills the vere process, deletes the checkpoint, restarts:
+
+      ...
+      ""
+
+    A or B enters an invalid move, beep sound is heard:
+
+      ...
+      ""
+
+    A and B tussle humorously over weird shared command line
+
+      ...
+      ""
+
+    B edits version 1 into version 2, automagically upgrading A
+
+      ...
+      ""
+
+    B logs out of A's tictactoe
+
+      ...
+      ""
+
+    B starts local tictactoe
+
+      ...
+      ""
+
+    B connects local tictactoe to A's server
+
+      ...
+      ""
+
+    B edits in version 3 ape, with web support
+
+      ...
+      ""
+    
+    A: watch editing of application
+   
+      ...
+      ""
+
+    B edits in mar, pub (very fast)
+
+      ...
+      ""
+
+    A: logs in to game url
+
+      ...
+      ""
+
+    A: brings up web talk
+
+      ...
+      ""
+
+    B: creates a local channel to talk about TTT
+
+      ...
+      ""
+
+    A: subscribes from the web UI to B's channel
+
+      ...
+      ""
+
+    C, D, and E: join the channel and give humorous advice
+
+      ...
+      ""
+
+    A: loses the game
+
+      ...
+      ""
+
+    B: sends bitcoin payment to A
+
+      ...
+      ""
+
+    A: points browser at blockchain.info, shows real payment
+
+      ...
+      ""
+
+close: 
+  credit screen 1:
+
+    *everyone who has ever worked/for at Tlon, in alphabetical 
+    order*,  
+ 
+  credit screen 2: 
+
+    *every non Tlon github uid that has contributed to our repository*
+
+  credit screen 3:
+
+    ~, huge
+
+

From c097c8101280851f0de5335ab956d392f9097f0d Mon Sep 17 00:00:00 2001
From: "C. Guy Yarvin" <cgyarvin@gmail.com>
Date: Wed, 20 May 2015 11:39:27 -0700
Subject: [PATCH 12/12] Fix some name issues.

---
 demo/commands.txt                             | 34 +++++++++----------
 demo/files/1-ape-tictactoe.hoon               |  2 +-
 demo/files/2-ape-tictactoe.hoon               |  2 +-
 demo/files/3-ape-tictactoe.hoon               |  2 +-
 ...tictactoe-game.hoon => mar-octo-game.hoon} |  0
 ...tictactoe-move.hoon => mar-octo-move.hoon} |  0
 ...tictactoe-hymn.hoon => pub-octo-hymn.hoon} |  0
 ...b-tictactoe-main.css => pub-octo-main.css} |  0
 ...pub-tictactoe-main.js => pub-octo-main.js} |  0
 demo/install2.sh                              |  4 +--
 demo/install3.sh                              | 16 ++++-----
 demo/script-3.txt                             |  1 -
 12 files changed, 30 insertions(+), 31 deletions(-)
 rename demo/files/{mar-tictactoe-game.hoon => mar-octo-game.hoon} (100%)
 rename demo/files/{mar-tictactoe-move.hoon => mar-octo-move.hoon} (100%)
 rename demo/files/{pub-tictactoe-hymn.hoon => pub-octo-hymn.hoon} (100%)
 rename demo/files/{pub-tictactoe-main.css => pub-octo-main.css} (100%)
 rename demo/files/{pub-tictactoe-main.js => pub-octo-main.js} (100%)

diff --git a/demo/commands.txt b/demo/commands.txt
index 9dbe8213f..b3097af41 100644
--- a/demo/commands.txt
+++ b/demo/commands.txt
@@ -79,37 +79,37 @@ Commands
 
   Helper files needed for version 2:
   
-    The %tictactoe-game mark, for game update diffs:
+    The %octo-game mark, for game update diffs:
 
-        /=demo=/mar/tictactoe-game/door/hook
-        urbit/$X/$X/in/$DEMO/mar/tictactoe-game/door.hook
-        $DEMO/files/mar-tictactoe-game.hoon 
+        /=demo=/mar/octo-game/door/hook
+        urbit/$X/$X/in/$DEMO/mar/octo-game/door.hook
+        $DEMO/files/mar-octo-game.hoon 
    
   Helper files needed for version 3:
 
-    The %tictactoe-move mark, for moves from the web:
+    The %octo-move mark, for moves from the web:
 
-        /=demo=/mar/tictactoe-move/door/hook
-        urbit/$X/$X/in/$DEMO/mar/tictactoe-move/door.hook
-        $DEMO/files/mar-tictactoe-move.hoon 
+        /=demo=/mar/octo-move/door/hook
+        urbit/$X/$X/in/$DEMO/mar/octo-move/door.hook
+        $DEMO/files/mar-octo-move.hoon 
  
     The HTML generator:
     
-        /=demo=/pub/tictactoe/fab/hymn/hook
-        urbit/$X/$X/in/$DEMO/pub/tictactoe/fab/hymn.hook
-        $DEMO/files/pub-tictactoe-hymn.hoon
+        /=demo=/pub/octo/fab/hymn/hook
+        urbit/$X/$X/in/$DEMO/pub/octo/fab/hymn.hook
+        $DEMO/files/pub-octo-hymn.hoon
 
     The CSS:
 
-        /=demo=/pub/tictactoe/src/main/css
-        urbit/$X/$X/in/$DEMO/pub/tictactoe/src/main.css
-        $DEMO/files/pub-tictactoe-main.css
+        /=demo=/pub/octo/src/main/css
+        urbit/$X/$X/in/$DEMO/pub/octo/src/main.css
+        $DEMO/files/pub-octo-main.css
 
     The JS:
 
-        /=demo=/pub/tictactoe/src/main/js
-        urbit/$X/$X/in/$DEMO/pub/tictactoe/src/main.js
-        $DEMO/files/pub-tictactoe-main.js
+        /=demo=/pub/octo/src/main/js
+        urbit/$X/$X/in/$DEMO/pub/octo/src/main.js
+        $DEMO/files/pub-octo-main.js
 
 [from tictactoe]
   
diff --git a/demo/files/1-ape-tictactoe.hoon b/demo/files/1-ape-tictactoe.hoon
index a22146447..e418af857 100644
--- a/demo/files/1-ape-tictactoe.hoon
+++ b/demo/files/1-ape-tictactoe.hoon
@@ -89,7 +89,7 @@
             ?-(lev %0 +>, %1 line, %2 line:show:prom)   ::
   ++  plow  |=  [lev=?(%0 %1 %2) mus=(unit tape)]       ::  complete print
             abet:(mean:(play lev) mus)                  ::
-  ++  prom  %^  emit  %pro  %&  :-  %acto               ::  update prompt
+  ++  prom  %^  emit  %pro  %&  :-  %tictactoe          ::  update prompt
             ": {~[(icon who.gam)]} to move (row/col): " ::  
   ++  rend  (turn `wall`~(tab go gam) |=(tape txt/+<))  ::  table print
   ++  show  (emit %mor rend)                            ::  update board
diff --git a/demo/files/2-ape-tictactoe.hoon b/demo/files/2-ape-tictactoe.hoon
index 34779285c..a3934572e 100644
--- a/demo/files/2-ape-tictactoe.hoon
+++ b/demo/files/2-ape-tictactoe.hoon
@@ -118,7 +118,7 @@
 ++  dish  |=(cad=card (dump 0 cad))                     ::  forward move
 ++  flet  |=(from ~(. et +< (~(got by q.eye) ost)))     ::  in old client
 ++  fret  |=(from ~(. et +< *sole-share))               ::  in new client
-++  like  |=(xir=ship |*(* [/octo [xir %octo] +<]))     ::  to friend
+++  like  |=(a=ship |*(* [/octo [a %tictactoe] +<]))    ::  to friend
 ++  link  |=  mot=mote  %+  dish(but `[| mot])  %peer   ::  subscribe to friend
           ((like p.mot) /octo/net/[?:(q.mot %x %o)])    ::  
 ++  pals  %+  turn  (pale hid (prix /sole))  |=  sink   ::  per console 
diff --git a/demo/files/3-ape-tictactoe.hoon b/demo/files/3-ape-tictactoe.hoon
index 009f8c41d..42365e72d 100644
--- a/demo/files/3-ape-tictactoe.hoon
+++ b/demo/files/3-ape-tictactoe.hoon
@@ -118,7 +118,7 @@
 ++  dish  |=(cad=card (dump 0 cad))                     ::  forward move
 ++  flet  |=(from ~(. et +< (~(got by q.eye) ost)))     ::  in old client
 ++  fret  |=(from ~(. et +< *sole-share))               ::  in new client
-++  like  |=(xir=ship |*(* [/octo [xir %octo] +<]))     ::  to friend
+++  like  |=(a=ship |*(* [/octo [a %tictactoe] +<]))    ::  to friend
 ++  link  |=  mot=mote  %+  dish(but `[| mot])  %peer   ::  subscribe to friend
           ((like p.mot) /octo/net/[?:(q.mot %x %o)])    ::  
 ++  pals  %+  turn  (pale hid (prix /sole))  |=  sink   ::  per console 
diff --git a/demo/files/mar-tictactoe-game.hoon b/demo/files/mar-octo-game.hoon
similarity index 100%
rename from demo/files/mar-tictactoe-game.hoon
rename to demo/files/mar-octo-game.hoon
diff --git a/demo/files/mar-tictactoe-move.hoon b/demo/files/mar-octo-move.hoon
similarity index 100%
rename from demo/files/mar-tictactoe-move.hoon
rename to demo/files/mar-octo-move.hoon
diff --git a/demo/files/pub-tictactoe-hymn.hoon b/demo/files/pub-octo-hymn.hoon
similarity index 100%
rename from demo/files/pub-tictactoe-hymn.hoon
rename to demo/files/pub-octo-hymn.hoon
diff --git a/demo/files/pub-tictactoe-main.css b/demo/files/pub-octo-main.css
similarity index 100%
rename from demo/files/pub-tictactoe-main.css
rename to demo/files/pub-octo-main.css
diff --git a/demo/files/pub-tictactoe-main.js b/demo/files/pub-octo-main.js
similarity index 100%
rename from demo/files/pub-tictactoe-main.js
rename to demo/files/pub-octo-main.js
diff --git a/demo/install2.sh b/demo/install2.sh
index 6e3e0430b..f818c04da 100755
--- a/demo/install2.sh
+++ b/demo/install2.sh
@@ -8,5 +8,5 @@ DESK=urbit/$X/$X/in/$DEMO
 echo "cp -f $COLD/2-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook"
 cp -f $COLD/1-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook
 
-echo "cp -f $COLD/mar-tictactoe-game.hoon $DESK/mar/tictactoe-game/door.hook"
-cp -f $COLD/mar-tictactoe-game.hoon $DESK/mar/tictactoe-game/door.hook
+echo "cp -f $COLD/mar-octo-game.hoon $DESK/mar/octo-game/door.hook"
+cp -f $COLD/mar-octo-game.hoon $DESK/mar/octo-game/door.hook
diff --git a/demo/install3.sh b/demo/install3.sh
index 261b846b7..734144344 100755
--- a/demo/install3.sh
+++ b/demo/install3.sh
@@ -8,14 +8,14 @@ DESK=urbit/$X/$X/in/$DEMO
 echo "cp -f $COLD/3-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook"
 cp -f $COLD/3-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook
 
-echo "cp -f $COLD/mar-tictactoe-game.hoon $DESK/mar/tictactoe-game/door.hook"
-cp -f $COLD/mar-tictactoe-game.hoon $DESK/mar/tictactoe-game/door.hook
+echo "cp -f $COLD/mar-octo-game.hoon $DESK/mar/octo-game/door.hook"
+cp -f $COLD/mar-octo-game.hoon $DESK/mar/octo-game/door.hook
 
-echo "cp -f $COLD/pub-tictactoe-hymn.hoon $DESK/pub/tictactoe/fab/hymn.hook"
-cp -f $COLD/pub-tictactoe-hymn.hoon $DESK/pub/tictactoe/fab/hymn.hook
+echo "cp -f $COLD/pub-octo-hymn.hoon $DESK/pub/octo/fab/hymn.hook"
+cp -f $COLD/pub-octo-hymn.hoon $DESK/pub/octo/fab/hymn.hook
 
-echo "cp -f $COLD/pub-tictactoe-main.css $DESK/pub/tictactoe/src/main.css"
-cp -f $COLD/pub-tictactoe-main.css $DESK/pub/tictactoe/src/main.css
+echo "cp -f $COLD/pub-octo-main.css $DESK/pub/octo/src/main.css"
+cp -f $COLD/pub-octo-main.css $DESK/pub/octo/src/main.css
 
-echo "cp -f $COLD/pub-tictactoe-main.js $DESK/pub/tictactoe/src/main.js"
-cp -f $COLD/pub-tictactoe-main.js $DESK/pub/tictactoe/src/main.js
+echo "cp -f $COLD/pub-octo-main.js $DESK/pub/octo/src/main.js"
+cp -f $COLD/pub-octo-main.js $DESK/pub/octo/src/main.js
diff --git a/demo/script-3.txt b/demo/script-3.txt
index 70492e69c..45e1e88c8 100644
--- a/demo/script-3.txt
+++ b/demo/script-3.txt
@@ -160,4 +160,3 @@ close:
 
     ~, huge
 
-