diff --git a/tools/run.py b/tools/run.py
index 3ad81103ebdd27c7cc66796534a35be83b1c825a..a33c153e3fb9c5cd25f2609e91950d4dca982b18 100755
--- a/tools/run.py
+++ b/tools/run.py
@@ -5,18 +5,24 @@
 #! nix-shell -i python3 -p "python3.withPackages (ps: [ ps.pyserial ])"
 
 import sys
+import os.path
 import base64
 import argparse
+import tarfile
 import serial
 
-from signal import signal, SIGINT
-from sys import exit
-
-
-
 parser = argparse.ArgumentParser(description="Executes python scripts on card10")
 parser.add_argument(
-    "script", type=argparse.FileType("r"), help="micropython file to execute"
+    "-r", "--run",
+    required=False,
+    type=argparse.FileType("r"),
+    help="MicroPython file to execute without writing to storage"
+)
+parser.add_argument(
+    "-u", "--upload",
+    required=False,
+    type=argparse.FileType("r"), 
+    help="Tarball to unpack and upload into apps folder",
 )
 parser.add_argument(
     "-d",
@@ -24,22 +30,11 @@ parser.add_argument(
     default="/dev/ttyACM0",
     help="Serial device of the pycardium console",
 )
-args = parser.parse_args()
 
-code = base64.b64encode(bytes(args.script.read(), "utf-8"))
+def applyBase64(s, code, fun="exec", extraSetup="", extraNewline=False):
+    n = 80
+    codechunks = [code[i:i+n] for i in range(0, len(code), n)]
 
-n=100
-codechunks = [code[i:i+n] for i in range(0, len(code), n)]
-
-with serial.Serial(port=args.device, baudrate=115200) as s:
-    
-    def handler(signal_received, frame):
-        # Handle any cleanup here
-        print('SIGINT or CTRL-C detected. Exiting gracefully')
-        s.write(b"\x03")
-        exit(0)
-    
-    signal(SIGINT, handler)
     s.write(b"\x03") # ctrl-c
     s.readline()
     s.write(b"import ubinascii; \r\n")
@@ -51,29 +46,66 @@ with serial.Serial(port=args.device, baudrate=115200) as s:
         s.readline() #dont echo this line
     s.write(b"'']\r\n")
     s.readline()
-        
-    s.write(b"exec(ubinascii.a2b_base64(''.join(code)))\r\n")
+    #print(s.readline())
+
+    for cmd in extraSetup:
+        if len(cmd) > 0:
+            s.write(bytes(cmd, 'utf-8'))
+            s.write(b"\r\n")
+            s.readline()
+        else:
+            s.write(b"\r\n")
+            s.readline()
+
+    s.write(bytes(fun, 'utf-8'))
+    s.write(b"(ubinascii.a2b_base64(''.join(code)))\r\n")
+    if extraNewline:
+        s.write(b"\r\n")
+        s.readline()
+        s.readline()
     s.readline()
-    
-        
-    
-
-
-    line = ""    
-    buf = b"" #s.read()
-    while True:
-#    while not line.startswith(">>>"):
-        char=""
-        
-        buf+=s.read()
-        
+
+
+args = parser.parse_args()
+
+if args.run is None and args.upload is None:
+    print("Either -e or -u has to be specified")
+
+with serial.Serial(port=args.device, baudrate=115200) as s:
+
+    if args.upload is not None:
+        tar = tarfile.TarFile.gzopen(args.upload.name)
+        for tarinfo in tar:
+            print(tarinfo.name)
+            payload = base64.b64encode(tar.extractfile(tarinfo.name).read())
+            applyBase64(s, payload,
+                        fun="with open('/apps/{}',\"w\") as f: f.write".format(tarinfo.name),
+                        extraSetup=[
+                            "try: os.mkdir(\"/apps/{}\")".format(os.path.dirname(tarinfo.name)),
+                            "except: pass",
+                            ""
+                        ],
+                        extraNewline=True)
+
+    elif args.run is not None:
+        payload = base64.b64encode(bytes(args.run.read(), "utf-8"))
+        applyBase64(s, payload)
+
         try:
-            char = buf.decode("utf-8")
-            print (char, end="")
             buf = b""
+            while True:
+                buf += s.read()
+                
+                try:
+                    char = buf.decode("utf-8")
+                    print(char, end="")
+                    buf = b""
 
-        except:
-            if(len(buf)>3):
-                print("ENCODING ERROR")
-                buf=""
-            
+                except UnicodeDecodeError as e:
+                    if len(buf) > 3:
+                        print(e)
+                        buf = b""
+
+        except KeyboardInterrupt:
+            print('CTRL-C detected. Exiting gracefully.')
+        s.write(b"\x03")