diff --git a/default.nix b/default.nix
index a1f33c3fc64607d4192c0152fba313b754cd8c5e..1a44a9f0504a6af7b49438e7290bd33ad83ca2a0 100644
--- a/default.nix
+++ b/default.nix
@@ -22,6 +22,7 @@ in stdenv.mkDerivation rec {
     ninja
     py
     py.pkgs.pillow
+    py.pkgs.pyserial
   ];
   src = ./.;
   buildCommand = ''
diff --git a/tools/run.py b/tools/run.py
new file mode 100755
index 0000000000000000000000000000000000000000..8860425cd230b3a333cb50c09194eb96afeb2741
--- /dev/null
+++ b/tools/run.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python3
+
+# or using nix-shell
+#!/usr/bin/env nix-shell
+#! nix-shell -i python3 -p "python3.withPackages (ps: [ ps.pyserial ])"
+
+import serial
+import base64
+import sys
+
+if len(sys.argv) == 1:
+    code = sys.stdin.read()
+else:
+    with open(sys.argv[1],"r") as f:
+        code = f.read()
+
+code = base64.b64encode(bytes(code, "ascii"))
+
+with serial.Serial(port="/dev/ttyACM0",baudrate=115200) as s:
+    s.write(b"\x03import ubinascii; exec(ubinascii.a2b_base64('" + code + b"'))\r\n")
+    s.readline()
+    s.readline()
+
+    t = ""
+    while not t.startswith(">>>"):
+        c = s.read()
+        if c == b'\n':
+            print(str(t))
+            t = ""
+        else:
+            t += chr(ord(c))
+