     (throw (ex-info "no server loop?" {})))
   (<!! server-loop))
 
+
+(defn- server-tick [state server-control repl-input]
+  (alt!!
+    server-control
+    ([v]
+      (when-not (nil? v)
+        (try
+          (handle-server-control state v)
+          (catch Exception e
+            (prn [:server-error e v])
+            state
+            ))))
+
+    repl-input
+    ([v]
+      (when-not (nil? v)
+        (try
+          (let [[msg result-chan] v]
+            (handle-repl-input state msg result-chan))
+          (catch Exception e
+            (prn [:repl-error e v])
+            state
+            ))))
+
+    (timeout 500)
+    ([_]
+      (try
+        (handle-server-control state [:idle])
+        (catch Exception e
+          (prn [:idle-error e])
+          state))
+      )))
+
+(defn- server-loop [state server-control repl-input repl-output]
+  (loop [state state]
+    (if-let [next-state (server-tick state server-control repl-input)]
+      (recur next-state)
+      (do (shutdown-server state)
+
+          ;; no more output coming
+          (async/close! repl-output)
+
+          ;; don't really need to close these since we should be the only ones reading them
+          ;; and closing one of them is a way to shut us down .. still like it clean
+          (async/close! repl-input)
+          (async/close! server-control)
+
+          ;; return value of this channel is the last compiler-state (includes repl-state)
+          (:compiler-state state)
+          ))))
+
 (defn start
   ([state config]
    (start state config default-compile-callback))

          ))))

(defn shutdown-server [state]
  (when-let [instance (get-in state [:server :instance])]
    (try
      (instance)

          ([v]
            (when-not (nil? v)
              (recur (handle-client-data state v)))
            )))

      ;; ensure that the channel is closed
      ;; http-kit seems to have a bug that leaves the server-loop running
      ;; if the server is shutdown while still having a connected websocket
      (hk/close channel)
      ))

(defn- ring-handler [server-control ring-request]
  (let [client-in (async/chan)
