install_zip command
diff --git a/commands.c b/commands.c
index 24bf242..7b2c2c1 100644
--- a/commands.c
+++ b/commands.c
@@ -836,6 +836,21 @@
     return 0;
 }
 
+static int
+cmd_install_zip(const char *name, void *cookie, int argc, const char *argv[],
+            PermissionRequestList *permissions)
+{
+    UNUSED(cookie);
+    CHECK_WORDS();
+    
+    if (argc != 1) {
+        LOGE("Command %s requires exactly one argument\n", name);
+        return 1;
+    }
+
+    return install_zip(argv[0]);
+}
+
 /*
  * Function definitions
  */
@@ -1211,6 +1226,9 @@
     ret = registerCommand("print", CMD_ARGS_WORDS, cmd_print, (void *)ctx);
     if (ret < 0) return ret;
 
+    ret = registerCommand("install_zip", CMD_ARGS_WORDS, cmd_install_zip, (void *)ctx);
+    if (ret < 0) return ret;
+
     /*
      * Functions
      */
diff --git a/extendedcommands.c b/extendedcommands.c
index 05ad475..e7ffb8f 100644
--- a/extendedcommands.c
+++ b/extendedcommands.c
@@ -50,7 +50,7 @@
     ui_print("Script Asserts: %s\n", script_assert_enabled ? "Enabled" : "Disabled");
 }
 
-void install_zip(const char* packagefilepath)
+int install_zip(const char* packagefilepath)
 {
     ui_print("\n-- Installing: %s\n", packagefilepath);
     set_sdcard_update_bootloader_message();
@@ -59,13 +59,14 @@
     if (status != INSTALL_SUCCESS) {
         ui_set_background(BACKGROUND_ICON_ERROR);
         ui_print("Installation aborted.\n");
-        return;
+        return 1;
     } 
     if (firmware_update_pending()) {
         ui_print("\nReboot via menu to complete\ninstallation.\n");
     }
     ui_set_background(BACKGROUND_ICON_NONE);
     ui_print("\nInstall from sdcard complete.\n");
+    return 0;
 }
 
 char* INSTALL_MENU_ITEMS[] = {  "apply sdcard:update.zip",
diff --git a/extendedcommands.h b/extendedcommands.h
index 12d6107..ddb619c 100644
--- a/extendedcommands.h
+++ b/extendedcommands.h
@@ -30,3 +30,7 @@
 
 void
 show_choose_zip_menu();
+
+int
+install_zip(const char* packagefilepath);
+