diff --git a/README.md b/README.md
index b9132e62198a1d7c14f53c6614c9db610f430a5d..428e5c7aec318ff56b7b549f54cb33f860a7b37d 100644
--- a/README.md
+++ b/README.md
@@ -57,51 +57,48 @@ import {
   State
 } from './hunks.js'
 
-function Name() {
+// our function name actually doesn't matter: hunks in js are named by their
+// location on disk
+export default function Name() {
   // this fn attaches handles to our function-object,
   Hunkify(this)
 
-  // inputs, outputs, and state are objects. they have a type (string identifier)
-  // see 'typeset.js'
-  // a name (doesn't have to be unique), and we pass them a handle to ourselves...
-  let inA = new Input('number', 'name', this)
-  // inputs, outputs and state are all kept locally in these arrays,
-  // if we don't include them here, the manager will have a hard time finding them ...
-  this.inputs.push(inA)
+  // inputs, outputs, and state are objects.
+  // they each have a type and a name
+  let inA = this.input('string', 'quiet')
+  let outB = this.output('string', 'loud')
 
-  let outB = new Output('number', 'name', this)
-  this.outputs.push(outB)
-
-  let stateItem = new State('string', 'name', 'startupValue')
-  this.states.push(stateItem)
+  // states take another argument: their default startup value
+  let stateItem = this.state('string', 'exclaim', '!')
 
   // State items also have change handlers,
   stateItem.onChange = (value) => {
-    // at this point, something external (probably a human)
-    // has requested that we change this state variable,
+    // at this point, a request to update this state item to the provided value
+    // has been made
     console.log('requests:', value)
     // we can reject that, by doing nothing here, or we can
     stateItem.set(value)
+    // or compute on it, set limits, etc
   }
 
   // hunks can choose to- or not- have init code.
-  // at init, the module has been loaded and state variables have been
+  // at init, the module has been loaded into the JS engine and state variables have been
   // recalled from any program save - so this is a good point
   // to check any of those, and setup accordingly ...
   this.init = () => {
     this.log('hello template world')
   }
 
+  // there are no rules within this closure, local functions, data, etc...
   let internalVariable = 'local globals'
-
-  function internalFunc(data) {
-    // scoped function, not accessible externally
-    // do work,
-    return (data)
+  function internalFunc(str) {
+    let caps = str.toUpperCase()
+    caps += stateItem.value
+    return (caps)
   }
 
   // to divide time between hunks, each has a loop function
-  // this is the hunks' runtime: a manager calls this once-per-round
+  // this is the hunks' runtime, and is called repeatedly, as the process runs
   // here is where we check inputs, put to outputs, do work, etc
   this.loop = () => {
     // typically we check inputs and outputs first,
@@ -114,12 +111,9 @@ function Name() {
     }
   }
 }
-
-// the hunk is also an ES6 module, this is how we export those:
-export default Name
 ```
 
-Hunks with DOM elements (to render into the browser's window) are a *tad* more complicated, here's an example:
+Hunks with DOM elements (to render custom html into the browser) are a bit more involved, here's a small example:
 
 ```javascript
 /*
@@ -130,51 +124,51 @@ debugger ! log anything !
 
 import { Hunkify, Input, Output, State } from '../hunks.js'
 
-function Logger() {
-    Hunkify(this, 'Logger')
+export default function ReferenceLogger() {
+  Hunkify(this)
 
-    let tolog = new Input('any', 'tolog', this)
-    this.inputs.push(tolog)
+  // hmm...
+  let tolog = new Input('reference', 'tolog', this)
+  this.inputs.push(tolog)
 
-    let prefix = new State('string', 'prefix', 'LOG:')
-    let logToConsole = new State('boolean', 'console', true)
-    this.states.push(prefix, logToConsole)
+  let prefix = new State('string', 'prefix', 'LOG:')
+  let logToConsole = new State('boolean', 'console', true)
+  this.states.push(prefix, logToConsole)
 
-    this.dom = {}
+  this.dom = {}
 
-    this.init = () => {
-        // manager calls this once
-        // it is loaded and state is updated (from program)
-        this.log('HELLO LOGGER')
-        this.dom = $('<div>').get(0)
-    }
+  this.init = () => {
+    this.dom = $('<div>').get(0)
+  }
 
-    this.onload = () => {
-      //error here
-      let text = $('<div>').addClass('txt').append('- >').get(0)
-      $(this.dom).append(text)
-    }
+  this.onload = () => {
+    //error here
+    let text = $('<div>').addClass('txt').append('- >').get(0)
+    $(this.dom).append(text)
+  }
 
-    this.loop = () => {
-        // this will be called once every round turn
-        // typically we check flow control first
-        if (tolog.io()) {
-            // an input is occupied, and the exit path is empty
-            let val = tolog.get()
-            if(Array.isArray(val)){
-              val = val.join(', ')
-            } else if (typeof val === "boolean"){
-              val = val.toString()
-            }
-            $(this.dom).children('.txt').html(val)
-            if (logToConsole.value === true) {
-                console.log(this.ind, prefix.value, val)
-            }
-        }
+  this.loop = () => {
+    // this will be called once every round turn
+    // typically we check flow control first
+    if (tolog.io()) {
+      // an input is occupied, and the exit path is empty
+      let raw = tolog.get()
+      let stringRep
+      if (Array.isArray(raw)) {
+        stringRep = raw.join(', ')
+      } else if (typeof raw === "boolean") {
+        stringRep = raw.toString()
+      } else {
+        // let js do w/e witchcraft it chooses
+        stringRep = raw
+      }
+      $(this.dom).children('.txt').html(stringRep)
+      if (logToConsole.value === true) {
+        console.log(this.ind, prefix.value, raw)
+      }
     }
+  }
 }
-
-export default Logger
 ```
 
 For a more involved example, see [the linechart](hunks/data/linechart.js).
diff --git a/hunks/adhoc/tpath.js b/hunks/adhoc/tpath.js
index 04f67947f8a17f05b992a973df0488c9a0133944..649c41a28900bd46db185b3f6f389c6d5b8d813c 100644
--- a/hunks/adhoc/tpath.js
+++ b/hunks/adhoc/tpath.js
@@ -37,7 +37,7 @@ export default function TPFCOUT(){
   let shortSet = this.state('boolean', 'shortpath', false)
   shortSet.onChange = (value) => {
     go = true
-    path = JSON.parse(JSON.stringify(shortpath.default.arr))
+    path = JSON.parse(JSON.stringify(smallpath.default.arr))
   }
   let sl2pathSet = this.state('boolean', 'sl2path', false)
   sl2pathSet.onChange = (value) => {
diff --git a/hunks/interface/threejs_ghost.js b/hunks/interface/threejs_ghost.js
index 456353193ac0169e47918582e73b11f0603f3382..8f3c089d4d3571485337dfec1eb235b39e1b7bcb 100644
--- a/hunks/interface/threejs_ghost.js
+++ b/hunks/interface/threejs_ghost.js
@@ -18,7 +18,7 @@ import { MeshLine, MeshLineMaterial } from '../../libs/three_meshline.module.js'
 
 let numSegs = 100
 
-export default function ThreeGhosts(){
+export default function ThreeGhosts() {
   Hunkify(this)
 
   let ptin = this.input('array', 'point')
@@ -34,8 +34,8 @@ export default function ThreeGhosts(){
   let lineWidth = 10
   let geometry = new THREE.Geometry()
   let startSegLength = 100 / numSegs
-  for(let i = numSegs; i > 0; i --){
-    geometry.vertices.push(new THREE.Vector3(startSegLength*i, startSegLength*i, startSegLength*i))
+  for (let i = numSegs; i > 0; i--) {
+    geometry.vertices.push(new THREE.Vector3(startSegLength * i, startSegLength * i, startSegLength * i))
   }
 
   let updatePts = []
@@ -47,9 +47,21 @@ export default function ThreeGhosts(){
     resolution: new THREE.Vector2(width, height)
   })
 
+  let pushToLine = (pt) => {
+    let v3 = new THREE.Vector3(pt[0], pt[1], pt[2])
+    geometry.vertices.push(v3)
+    geometry.vertices.shift()
+    line.advance(v3)
+  }
+
   let camera = new THREE.PerspectiveCamera(75, width / height, 1, 10000)
   camera.up.set(0, 0, 1)
 
+  let bbox = new THREE.Box3()
+  let bbCenter = new THREE.Vector3()
+  let bbSize = new THREE.Vector3()
+  console.log('line', line)
+
   this.onload = (dom) => {
     let scene = new THREE.Scene()
     scene.background = new THREE.Color(0xc8e6e2)
@@ -68,17 +80,36 @@ export default function ThreeGhosts(){
     //let controls = new OrbitControls(camera, this.dom)
     //controls.update()
     camera.position.set(840, 100, 1300)
-    camera.lookAt(new THREE.Vector3(900,600,10))
+    camera.lookAt(new THREE.Vector3(900, 600, 10))
+
+    console.log(line)
 
     let animate = function() {
-        requestAnimationFrame(animate)
-        if(updatePts.length > 0){
-          let nextpt = updatePts.shift()
-          // advance removes the oldest position, so we should start w/ the # we want
-          line.advance(new THREE.Vector3(nextpt[0], nextpt[1], nextpt[2]))
-        }
-        //controls.update()
-        renderer.render(scene, camera)
+      //
+      // requestAnimationFrame(animate)
+      setTimeout(animate, 500)
+      if (updatePts.length > 0) {
+        let nextpt = updatePts.shift()
+        // advance removes the oldest position, so we should start w/ the # we want
+        pushToLine(nextpt)
+        // do bounding box...
+        bbox.setFromPoints(geometry.vertices)
+        bbox.getCenter(bbCenter)
+        bbox.getSize(bbSize)
+        const maxDim = Math.max(bbSize.x, bbSize.y, bbSize.z)
+        const fov = camera.fov * (Math.PI / 180)
+        let cameraZ = Math.abs(maxDim / 4 * Math.tan(fov * 2))
+        cameraZ *= cameraZ
+        console.log(cameraZ)
+        camera.position.z = cameraZ
+        const minZ = bbox.min.z
+        const cameraToFarEdge = (minZ < 0) ? -minZ + cameraZ : cameraZ - minZ
+        camera.far = cameraToFarEdge * 3
+        camera.updateProjectionMatrix()
+        camera.lookAt(bbCenter)
+      }
+      //controls.update()
+      renderer.render(scene, camera)
     }
     // kickstart
     animate()
@@ -102,9 +133,8 @@ export default function ThreeGhosts(){
   }
 
   this.loop = () => {
-    if(ptin.io()){
+    if (ptin.io()) {
       updatePts.push(ptin.get())
-
       /*
       geometry.vertices.push(new THREE.Vector3(pt[0], pt[1], pt[2]))
       if(geometry.vertices.length > 32){
diff --git a/save/contexts/cuttlefish/0ghost.json b/save/contexts/cuttlefish/0ghost.json
new file mode 100644
index 0000000000000000000000000000000000000000..9e5951fb5d41eb30dfbb9c024f1cd8249c0390c8
--- /dev/null
+++ b/save/contexts/cuttlefish/0ghost.json
@@ -0,0 +1,124 @@
+{
+  "interpreterName": "cuttlefish",
+  "interpreterVersion": "v0.1",
+  "hunks": [
+    {
+      "type": "manager",
+      "name": "nrol",
+      "inputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray",
+          "connections": [
+            {
+              "inHunkIndex": "1",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "view",
+      "name": "tlview",
+      "inputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray",
+          "connections": [
+            {
+              "inHunkIndex": "0",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "adhoc/tpath",
+      "name": "adhoc/tpath_2",
+      "outputs": [
+        {
+          "name": "position",
+          "type": "array",
+          "connections": [
+            {
+              "inHunkIndex": "3",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ],
+      "states": [
+        {
+          "name": "mm/pix",
+          "type": "number",
+          "value": "1"
+        },
+        {
+          "name": "longpath",
+          "type": "boolean",
+          "value": "false"
+        },
+        {
+          "name": "shortpath",
+          "type": "boolean",
+          "value": "false"
+        },
+        {
+          "name": "sl2path",
+          "type": "boolean",
+          "value": "false"
+        }
+      ]
+    },
+    {
+      "type": "adhoc/saturn",
+      "name": "adhoc/saturn_3",
+      "inputs": [
+        {
+          "name": "posn",
+          "type": "array"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "posn",
+          "type": "array",
+          "connections": [
+            {
+              "inHunkIndex": "4",
+              "inHunkInput": "0"
+            }
+          ]
+        },
+        {
+          "name": "motionSegment",
+          "type": "MDmseg"
+        }
+      ]
+    },
+    {
+      "type": "interface/threejs_ghost",
+      "name": "interface/threejs_ghost_5",
+      "inputs": [
+        {
+          "name": "point",
+          "type": "array"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/save/contexts/cuttlefish/dbg.json b/save/contexts/cuttlefish/dbg.json
index 8686d30ff9841bc92dae745cf9a924d7ee97eb27..9e5951fb5d41eb30dfbb9c024f1cd8249c0390c8 100644
--- a/save/contexts/cuttlefish/dbg.json
+++ b/save/contexts/cuttlefish/dbg.json
@@ -63,7 +63,22 @@
       ],
       "states": [
         {
-          "name": "reset",
+          "name": "mm/pix",
+          "type": "number",
+          "value": "1"
+        },
+        {
+          "name": "longpath",
+          "type": "boolean",
+          "value": "false"
+        },
+        {
+          "name": "shortpath",
+          "type": "boolean",
+          "value": "false"
+        },
+        {
+          "name": "sl2path",
           "type": "boolean",
           "value": "false"
         }
@@ -90,22 +105,14 @@
           ]
         },
         {
-          "name": "outx",
-          "type": "number"
-        },
-        {
-          "name": "outy",
-          "type": "number"
-        },
-        {
-          "name": "outz",
-          "type": "number"
+          "name": "motionSegment",
+          "type": "MDmseg"
         }
       ]
     },
     {
       "type": "interface/threejs_ghost",
-      "name": "interface/threejs_ghost_4",
+      "name": "interface/threejs_ghost_5",
       "inputs": [
         {
           "name": "point",
diff --git a/save/contexts/cuttlefish/ghost.json b/save/contexts/cuttlefish/ghost.json
new file mode 100644
index 0000000000000000000000000000000000000000..9e5951fb5d41eb30dfbb9c024f1cd8249c0390c8
--- /dev/null
+++ b/save/contexts/cuttlefish/ghost.json
@@ -0,0 +1,124 @@
+{
+  "interpreterName": "cuttlefish",
+  "interpreterVersion": "v0.1",
+  "hunks": [
+    {
+      "type": "manager",
+      "name": "nrol",
+      "inputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray",
+          "connections": [
+            {
+              "inHunkIndex": "1",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "view",
+      "name": "tlview",
+      "inputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray",
+          "connections": [
+            {
+              "inHunkIndex": "0",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "adhoc/tpath",
+      "name": "adhoc/tpath_2",
+      "outputs": [
+        {
+          "name": "position",
+          "type": "array",
+          "connections": [
+            {
+              "inHunkIndex": "3",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ],
+      "states": [
+        {
+          "name": "mm/pix",
+          "type": "number",
+          "value": "1"
+        },
+        {
+          "name": "longpath",
+          "type": "boolean",
+          "value": "false"
+        },
+        {
+          "name": "shortpath",
+          "type": "boolean",
+          "value": "false"
+        },
+        {
+          "name": "sl2path",
+          "type": "boolean",
+          "value": "false"
+        }
+      ]
+    },
+    {
+      "type": "adhoc/saturn",
+      "name": "adhoc/saturn_3",
+      "inputs": [
+        {
+          "name": "posn",
+          "type": "array"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "posn",
+          "type": "array",
+          "connections": [
+            {
+              "inHunkIndex": "4",
+              "inHunkInput": "0"
+            }
+          ]
+        },
+        {
+          "name": "motionSegment",
+          "type": "MDmseg"
+        }
+      ]
+    },
+    {
+      "type": "interface/threejs_ghost",
+      "name": "interface/threejs_ghost_5",
+      "inputs": [
+        {
+          "name": "point",
+          "type": "array"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file