diff a/hat/hatrun b/hat/hatrun
--- /dev/null
+++ b/hat/hatrun
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import static bldr.Bldr.*;           // all the helpers are here 
+import static java.nio.file.Files.*; // so we can use isDirectory(path);
+
+void main(String[] args) {
+   var hatDir = new Root();
+   if (args.length==0){
+      println("""
+              usage:
+                 hatrun [headless] backend package args ...
+                 headless : Optional passes -Dheadless=true to app
+                 backend  : opencl|cuda|spirv|ptx|mock
+                 package  : the examples package (and dirname under hat/examples)
+                 Class name is assumed to be package.Main 
+              """);
+      System.exit(1);
+   } else{
+     var buildDir = assertOrThrow(hatDir.buildDir(), Files::isDirectory, "Build Directory");
+     
+     int argc=0;
+     boolean headless = args[argc].equals("headless");
+     if (headless){
+        argc++;
+     }
+     if (argc<args.length 
+           && hatDir.path().resolve("backends") instanceof Path backendsDir && Files.isDirectory(backendsDir)){
+        var classPath = new ArrayList<>(List.of(buildDir.resolve("hat-1.0.jar")));
+        var backendDir = backendsDir.resolve(args[argc++]);
+        if (argc<args.length && (Files.isDirectory(backendDir) || backendDir.getFileName().toString().equals("java"))){
+           if (Files.isDirectory(backendDir)){
+              classPath.add(assertOrThrow(buildDir.resolve("hat-backend-"+backendDir.getFileName()+"-1.0.jar"), Files::isRegularFile," backend dir"));
+           }else{
+              classPath.add(assertOrThrow(backendsDir.resolve("shared/src/main/resources"), Files::isDirectory, "backend dir"));
+           }
+           if (argc<args.length &&
+                assertOrThrow(hatDir.path().resolve("examples"), Files::isDirectory, "Examples Dir") instanceof Path examplesDir){
+              var exampleDir = assertOrThrow(examplesDir.resolve(args[argc++]), Files::isDirectory, "Example dir");
+              classPath.add(assertOrThrow(buildDir.resolve("hat-example-"+exampleDir.getFileName()+"-1.0.jar"), Files::isRegularFile," example jar "));
+              final int finalArgc = argc; //sigh
+              
+              java($->$
+                 .vmopts(
+                   "--enable-preview",
+                   "--enable-native-access=ALL-UNNAMED",
+                   "--add-exports=java.base/jdk.internal=ALL-UNNAMED",
+                   "-Djava.library.path=build:/usr/local/lib"
+                 )
+                 .when(headless, $$->$$
+                    .vmopts("-Dheadless=true")
+                 )
+                 .class_path(classPath)
+                 .main_class(exampleDir.getFileName() + ".Main")
+                 .args(Arrays.copyOfRange(args, finalArgc, args.length))
+              );
+ 
+           }else{
+              println("no example");
+           }
+        }else{
+           println("no backend");
+        }
+     }else{
+        println("junk");
+     }
+
+   }
+}
