diff --git a/build.gradle b/build.gradle
index f6f4438..4513c15 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,11 +1,31 @@
 plugins {
-    id 'java-library'
+    id 'java'
+    id 'application'
+    id 'com.github.johnrengelman.shadow' version '5.0.0'
 }
 
 dependencies {
+	implementation 'commons-cli:commons-cli:1.4'
     //testImplementation 'junit:junit:4.12'
 }
 
 repositories {
     jcenter()
+}
+
+mainClassName = 'link.infra.packwiz.installer.Main'
+
+jar {
+    manifest {
+        attributes(
+            'Main-Class': 'link.infra.packwiz.installer.Main'
+        )
+    }
+}
+
+// Commons CLI is already included in packwiz-installer-bootstrap
+shadowJar {
+   dependencies {
+       exclude(dependency('commons-cli:commons-cli:1.4'))
+   }
 }
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 94336fc..5c2d1cf 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 290541c..f4d7b2b 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index cccdd3d..b0d6d0a 100644
--- a/gradlew
+++ b/gradlew
@@ -1,5 +1,21 @@
 #!/usr/bin/env sh
 
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
 ##############################################################################
 ##
 ##  Gradle start up script for UN*X
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
 APP_BASE_NAME=`basename "$0"`
 
 # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
 
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD="maximum"
diff --git a/gradlew.bat b/gradlew.bat
index f955316..9991c50 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -1,3 +1,19 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
 @if "%DEBUG%" == "" @echo off
 @rem ##########################################################################
 @rem
@@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0
 set APP_HOME=%DIRNAME%
 
 @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
 
 @rem Find java.exe
 if defined JAVA_HOME goto findJavaFromJavaHome
diff --git a/src/main/java/link/infra/packwiz/installer/InstallWindow.java b/src/main/java/link/infra/packwiz/installer/InstallWindow.java
new file mode 100644
index 0000000..4a7a44a
--- /dev/null
+++ b/src/main/java/link/infra/packwiz/installer/InstallWindow.java
@@ -0,0 +1,99 @@
+package link.infra.packwiz.installer;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.EventQueue;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.UIManager;
+import javax.swing.border.EmptyBorder;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+public class InstallWindow {
+	
+	// TODO: move to seperate file, make usable without GUI
+
+	private JFrame frmPackwizlauncher;
+	private UpdateManager updateManager = new UpdateManager();
+
+	/**
+	 * Launch the application.
+	 */
+	public static void main(String[] args) {
+		EventQueue.invokeLater(new Runnable() {
+			public void run() {
+				try {
+					UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+					InstallWindow window = new InstallWindow();
+					window.frmPackwizlauncher.setVisible(true);
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		});
+	}
+
+	/**
+	 * Create the application.
+	 */
+	public InstallWindow() {
+		initialize();
+	}
+
+	/**
+	 * Initialize the contents of the frame.
+	 */
+	private void initialize() {
+		frmPackwizlauncher = new JFrame();
+		frmPackwizlauncher.setTitle("Updating modpack...");
+		frmPackwizlauncher.setBounds(100, 100, 493, 95);
+		frmPackwizlauncher.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		frmPackwizlauncher.setLocationRelativeTo(null);
+		
+		JPanel panel = new JPanel();
+		panel.setBorder(new EmptyBorder(10, 10, 10, 10));
+		frmPackwizlauncher.getContentPane().add(panel, BorderLayout.CENTER);
+		panel.setLayout(new BorderLayout(0, 0));
+		
+		JProgressBar progressBar = new JProgressBar();
+		progressBar.setValue(50);
+		panel.add(progressBar, BorderLayout.CENTER);
+		
+		JLabel lblProgresslabel = new JLabel("Loading...");
+		panel.add(lblProgresslabel, BorderLayout.SOUTH);
+		
+		JPanel panel_1 = new JPanel();
+		panel_1.setBorder(new EmptyBorder(0, 5, 0, 5));
+		frmPackwizlauncher.getContentPane().add(panel_1, BorderLayout.EAST);
+		GridBagLayout gbl_panel_1 = new GridBagLayout();
+		panel_1.setLayout(gbl_panel_1);
+		
+		JButton btnOptions = new JButton("Options...");
+		btnOptions.setAlignmentX(Component.CENTER_ALIGNMENT);
+		GridBagConstraints gbc_btnOptions = new GridBagConstraints();
+		gbc_btnOptions.gridx = 0;
+		gbc_btnOptions.gridy = 0;
+		panel_1.add(btnOptions, gbc_btnOptions);
+		
+		JButton btnCancel = new JButton("Cancel");
+		btnCancel.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent arg0) {
+				updateManager.cleanup();
+				frmPackwizlauncher.dispose();
+			}
+		});
+		btnCancel.setAlignmentX(Component.CENTER_ALIGNMENT);
+		GridBagConstraints gbc_btnCancel = new GridBagConstraints();
+		gbc_btnCancel.gridx = 0;
+		gbc_btnCancel.gridy = 1;
+		panel_1.add(btnCancel, gbc_btnCancel);
+	}
+
+}
diff --git a/src/main/java/link/infra/packwiz/installer/Main.java b/src/main/java/link/infra/packwiz/installer/Main.java
index de20578..7fd89ce 100644
--- a/src/main/java/link/infra/packwiz/installer/Main.java
+++ b/src/main/java/link/infra/packwiz/installer/Main.java
@@ -1,99 +1,68 @@
 package link.infra.packwiz.installer;
 
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.EventQueue;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
+import javax.swing.JOptionPane;
 
-import javax.swing.JButton;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JProgressBar;
-import javax.swing.UIManager;
-import javax.swing.border.EmptyBorder;
-import java.awt.event.ActionListener;
-import java.awt.event.ActionEvent;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
 
 public class Main {
 	
-	// TODO: move to seperate file, make usable without GUI
-
-	private JFrame frmPackwizlauncher;
-	private UpdateManager updateManager = new UpdateManager();
-
-	/**
-	 * Launch the application.
-	 */
 	public static void main(String[] args) {
-		EventQueue.invokeLater(new Runnable() {
-			public void run() {
-				try {
-					UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
-					Main window = new Main();
-					window.frmPackwizlauncher.setVisible(true);
-				} catch (Exception e) {
-					e.printStackTrace();
-				}
-			}
-		});
+		Options options = new Options();
+		options.addOption("g", "no-gui", false, "Don't display a GUI to show update progress");
+		
+		CommandLineParser parser = new DefaultParser();
+		CommandLine cmd = null;
+		try {
+			// Allow any arguments, we're going to exit(1) anyway
+			cmd = parser.parse(options, args, false);
+		} catch (ParseException e) {
+			e.printStackTrace();
+			JOptionPane.showMessageDialog(null, e.getMessage(), "packwiz-installer", JOptionPane.ERROR_MESSAGE);
+			System.exit(1);
+		}
+		if (cmd.hasOption("no-gui")) {
+			System.out.println("This program must be run through packwiz-installer-bootstrap. Use --bootstrap-no-update to disable updating.");
+			System.exit(1);
+		} else {
+			JOptionPane.showMessageDialog(null, "This program must be run through packwiz-installer-bootstrap. Use --bootstrap-no-update to disable updating.", "packwiz-installer", JOptionPane.ERROR_MESSAGE);
+			System.exit(1);
+		}
+	}
+	
+	public Main(String[] args) {
+		Options options = new Options();
+		addNonBootstrapOptions(options);
+		addBootstrapOptions(options);
+		
+		CommandLineParser parser = new DefaultParser();
+		CommandLine cmd = null;
+		try {
+			cmd = parser.parse(options, args);
+		} catch (ParseException e) {
+			e.printStackTrace();
+			JOptionPane.showMessageDialog(null, e.getMessage(), "packwiz-installer", JOptionPane.ERROR_MESSAGE);
+			System.exit(1);
+		}
+		
+		System.out.println("Hello World!");
 	}
 
-	/**
-	 * Create the application.
-	 */
-	public Main() {
-		initialize();
+	// Called by packwiz-installer-bootstrap to set up the help command
+	public static void addNonBootstrapOptions(Options options) {
+		options.addOption("w", "welp", false, "Testing options");
 	}
-
-	/**
-	 * Initialize the contents of the frame.
-	 */
-	private void initialize() {
-		frmPackwizlauncher = new JFrame();
-		frmPackwizlauncher.setTitle("Updating modpack...");
-		frmPackwizlauncher.setBounds(100, 100, 493, 95);
-		frmPackwizlauncher.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-		frmPackwizlauncher.setLocationRelativeTo(null);
-		
-		JPanel panel = new JPanel();
-		panel.setBorder(new EmptyBorder(10, 10, 10, 10));
-		frmPackwizlauncher.getContentPane().add(panel, BorderLayout.CENTER);
-		panel.setLayout(new BorderLayout(0, 0));
-		
-		JProgressBar progressBar = new JProgressBar();
-		progressBar.setValue(50);
-		panel.add(progressBar, BorderLayout.CENTER);
-		
-		JLabel lblProgresslabel = new JLabel("Loading...");
-		panel.add(lblProgresslabel, BorderLayout.SOUTH);
-		
-		JPanel panel_1 = new JPanel();
-		panel_1.setBorder(new EmptyBorder(0, 5, 0, 5));
-		frmPackwizlauncher.getContentPane().add(panel_1, BorderLayout.EAST);
-		GridBagLayout gbl_panel_1 = new GridBagLayout();
-		panel_1.setLayout(gbl_panel_1);
-		
-		JButton btnOptions = new JButton("Options...");
-		btnOptions.setAlignmentX(Component.CENTER_ALIGNMENT);
-		GridBagConstraints gbc_btnOptions = new GridBagConstraints();
-		gbc_btnOptions.gridx = 0;
-		gbc_btnOptions.gridy = 0;
-		panel_1.add(btnOptions, gbc_btnOptions);
-		
-		JButton btnCancel = new JButton("Cancel");
-		btnCancel.addActionListener(new ActionListener() {
-			public void actionPerformed(ActionEvent arg0) {
-				updateManager.cleanup();
-				frmPackwizlauncher.dispose();
-			}
-		});
-		btnCancel.setAlignmentX(Component.CENTER_ALIGNMENT);
-		GridBagConstraints gbc_btnCancel = new GridBagConstraints();
-		gbc_btnCancel.gridx = 0;
-		gbc_btnCancel.gridy = 1;
-		panel_1.add(btnCancel, gbc_btnCancel);
+	
+	// TODO: link these somehow so they're only defined once?
+	private static void addBootstrapOptions(Options options) {
+		options.addOption(null, "bootstrap-update-url", true, "Github API URL for checking for updates");
+		options.addOption(null, "bootstrap-no-update", false, "Don't update packwiz-installer");
+		options.addOption(null, "bootstrap-main-jar", true, "Location of the packwiz-installer JAR file");
+		options.addOption("g", "no-gui", false, "Don't display a GUI to show update progress");
+		options.addOption("h", "help", false, "Display this message");
 	}
-
+	
 }