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..27ea7879b52e9c86533ed45d2194a3d2eb9b9773
--- /dev/null
+++ b/tools/run.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+
+# or using nix-shell
+#!/usr/bin/env nix-shell
+#! nix-shell -i python3 -p "python3.withPackages (ps: [ ps.pyserial ])"
+
+import sys
+import base64
+import argparse
+import serial
+
+parser = argparse.ArgumentParser(description="Executes python scripts on card10")
+parser.add_argument(
+    "script", type=argparse.FileType("r"), help="micropython file to execute"
+)
+parser.add_argument(
+    "-d",
+    "--device",
+    default="/dev/ttyACM0",
+    help="Serial device of the pycardium console",
+)
+args = parser.parse_args()
+
+code = base64.b64encode(bytes(args.script.read(), "utf-8"))
+
+with serial.Serial(port=args.device, baudrate=115200) as s:
+    s.write(b"\x03import ubinascii; exec(ubinascii.a2b_base64('" + code + b"'))\r\n")
+    s.readline()
+    s.readline()
+
+    line = ""
+    while not line.startswith(">>>"):
+        char = s.read().decode("utf-8")
+        if char == "\n":
+            print(line)
+            line = ""
+        else:
+            line += char