                            :load-nss load})))
   (swap! tracker assoc ::track/load nil ::track/unload nil)
   (println :ok))
+
+(defn recursive-register [watcher root]
+  (Files/walkFileTree
+    root
+    (proxy [SimpleFileVisitor] []
+      (preVisitDirectory [^Path dir attrs]
+        (.register dir
+                   watcher
+                   (into-array WatchEvent$Kind
+                               [StandardWatchEventKinds/ENTRY_CREATE
+                                StandardWatchEventKinds/ENTRY_DELETE
+                                StandardWatchEventKinds/ENTRY_MODIFY])
+                   (into-array WatchEvent$Modifier
+                               [SensitivityWatchEventModifier/HIGH]))
+        FileVisitResult/CONTINUE))))
+
+(defn start-watch [^ExecutorService exec ^FileSystem fs refresh-opts]
+  (.submit exec
+           ^Callable
+           (fn []
+             (try
+               (with-open [ws (.newWatchService fs)]
+                 (doseq [^Path root (map #(.getPath fs % (make-array String 0))
+                                         (:source-dirs refresh-opts))]
+                   (recursive-register ws root))
+                 (while true
+                   (when-let [k (.poll ws 300 TimeUnit/MILLISECONDS)]
+                     (when-let [events (and (.reset k)
+                                            (seq (.pollEvents k)))]
+                       (doseq [^WatchEvent e events]
+                         (if (= (.kind e) StandardWatchEventKinds/ENTRY_CREATE)
+                           (let [f (.context e)]
+                             (if (Files/isDirectory f (make-array LinkOption 0))
+                               (recursive-register ws f)))))
+                       (when (some (comp #(or (.endsWith % ".cljs")
+                                              (.endsWith % ".cljc"))
+                                         str
+                                         #(.context %))
+                                   events)
+                         (println "Watcher Refreshing...")
+                         (refresh* refresh-opts))))))
+               (catch IOException io
+                 (comment (println "REPL shutdown detected.")))
+               (catch InterruptedException ie
+                 (comment (println "Interrupted")))
+               (catch Exception e
+                 (binding [*out* *err*]
+                   (println (.getMessage e))
+                   (println (.printStackTrace e *out*))))
+               (finally
+                 (println "Shutting down watcher.")
+                 (.shutdown exec))))))
+
+(defn stop-watch []
+  (.shutdownNow watch-exec))
 
 (defn maybe-quoted->symbol [symbol-or-list]
   (if (list? symbol-or-list)

      {source-dirs ["src"]}}]
  (let [refresher (atom refresher)
        tracker (atom (track/tracker))
        disable-unload (atom (into #{} disable-unload))
        disable-load (atom (into #{'cljs.core
                                   'clojure.browser.repl
                                   'clojure.browser.net}
                                 disable-load))
        initial-build-complete? (promise)
        closed-settings (select-keys closed-settings
                                     [:before
                                      :after

                        before
                        after
                        state
                        add-all?
                        compiler-env]
                 :or
                 {compiler-env env/*compiler*}}]
  (doseq [s (filter some? [before after state])]
    (assert (symbol? s) "value must be a symbol")
    (assert (namespace s)
