     (catch Throwable ex
       (println (str ex)))))
 
+(defn load-stream [jse stream]
+  (with-open [r (io/reader stream)]
+    (let [env {:ns (@namespaces *cljs-ns*) :context :statement :locals {}}
+          pbr (clojure.lang.LineNumberingPushbackReader. r)
+          eof (Object.)]
+      (loop [r (read pbr false eof false)]
+        (let [env (assoc env :ns (@namespaces *cljs-ns*))]
+          (when-not (identical? eof r)
+            (eval1 jse env r)
+            (recur (read pbr false eof false))))))))
+
 (defn load-file
   [jse f]
   (binding [*cljs-ns* 'cljs.user]
-    (let [env {:ns (@namespaces *cljs-ns*) :context :statement :locals {}}
-          res (if (= \/ (first f)) f (io/resource f))]
+    (let [res (if (= \/ (first f)) f (io/resource f))]
       (assert res (str "Can't find " f " in classpath"))
-      (with-open [r (io/reader res)]
-        (let [pbr (clojure.lang.LineNumberingPushbackReader. r)
-              eof (Object.)]
-          (loop [r (read pbr false eof false)]
-            (let [env (assoc env :ns (@namespaces *cljs-ns*))]
-              (when-not (identical? eof r)
-                (eval1 jse env r)
-                (recur (read pbr false eof false))))))))))
+      (load-stream jse res))))
+
+(def loaded-libs (atom #{}))
+
+(defn require [^javax.script.ScriptEngine jse rule]
+  (when-not (contains? @loaded-libs rule)
+    (let [path (string/replace (munge rule) \. java.io.File/separatorChar)
+          cljs-path (str path ".cljs")
+          js-path (str path ".js")]
+      (if-let [res (io/resource cljs-path)]
+        (binding [*cljs-ns* 'cljs.user]
+          (load-stream jse res))
+        (if-let [res (io/resource js-path)]
+          (.eval jse (io/reader res))
+          (throw (Exception. (str "Cannot find " cljs-path " or " js-path " in classpath")))))
+      (swap! loaded-libs conj rule))))
 
 (defn repl-env
   "Returns a fresh JS environment, suitable for passing to repl.

        (cond
         lb (:name lb)
         
         ;;todo - resolve ns aliases when we have them
         (namespace sym)
         (symbol (str (namespace sym) "." (munge (name sym))))

         (.contains s ".")
         (munge (let [idx (.indexOf s ".")

                                        libs))))
                {} args)]
    (set! *cljs-ns* name)
    (clojure.core/require 'cljs.core)
    (doseq [nsym (vals requires-macros)]
      (clojure.core/require nsym))
    (swap! namespaces #(-> %
                           (assoc-in [name :name] name)
                           (assoc-in [name :requires] requires)
