       ;; :else
       (send msg {:err (pr-str [:FIXME result])}))))
 
-(defn do-cljs-eval [{::keys [state-ref worker] :keys [ns session code runtime-id] :as msg}]
+(defn do-cljs-eval [{::keys [worker] :keys [ns session code runtime-id] :as msg}]
   (let [reader (StringReader. code)
 
         session-id
-        (-> session meta :id str)]
-
-    ;; :last-msg is used by the print loop started by repl-init
+        (-> session meta :id str)
+
+        {:keys [last-msg-ref] :as repl-state}
+        (get @session #'*repl-state*)]
+
+    ;; :last-msg-ref is used by the print loop started by repl-init
     ;; to ensure that all prints use the latest message id when sending it out
-    (swap! state-ref assoc :last-msg msg)
+    ;; FIXME: this is completely pointless with clone'd sessions
+    ;; lets just hope eval is only ever done against one of the clones ...
+    (reset! last-msg-ref msg)
 
     (loop []
       (when-let [build-state (repl-impl/worker-build-state worker)]

    ;; cleanup if worker exits
    (go (<! proc-stop)
        (async/close! watch-chan)
        (worker-exit state-ref session msg))

    ;; watch worker for specific messages (ie. out/err)
    ;; send :err/:out with latest msg id to make tools happy

  (:import [java.io StringReader]
           [clojure.lang Var]))

(def ^:dynamic *repl-state* nil)

(defn send [{:keys [transport session id] :as req} {:keys [status] :as msg}]
  (let [res
