diff --git a/src/Squirrel/IUpdateManager.cs b/src/Squirrel/IUpdateManager.cs
index 1edc11e4e..8ca122164 100644
--- a/src/Squirrel/IUpdateManager.cs
+++ b/src/Squirrel/IUpdateManager.cs
@@ -23,12 +23,19 @@ public enum ShortcutLocation {
         AppRoot = 1 << 3
     }
 
+    public enum UpdaterIntention {
+        Install,
+        Update
+    }
+
     public interface IUpdateManager : IDisposable, IEnableLogger
     {
         /// <summary>
         /// Fetch the remote store for updates and compare against the current 
         /// version to determine what updates to download.
         /// </summary>
+        /// <param name="intention">Indicates whether the UpdateManager is used
+        /// in a Install or Update scenario.</param>
         /// <param name="ignoreDeltaUpdates">Set this flag if applying a release
         /// fails to fall back to a full release, which takes longer to download
         /// but is less error-prone.</param>
@@ -36,7 +43,7 @@ public interface IUpdateManager : IDisposable, IEnableLogger
         /// will return values from 0-100 and Complete, or Throw</param>
         /// <returns>An UpdateInfo object representing the updates to install.
         /// </returns>
-        Task<UpdateInfo> CheckForUpdate(bool ignoreDeltaUpdates = false, Action<int> progress = null);
+        Task<UpdateInfo> CheckForUpdate(bool ignoreDeltaUpdates = false, Action<int> progress = null, UpdaterIntention intention = UpdaterIntention.Update);
 
         /// <summary>
         /// Download a list of releases into the local package directory.
diff --git a/src/Squirrel/UpdateManager.ApplyReleases.cs b/src/Squirrel/UpdateManager.ApplyReleases.cs
index 1dbd7c5f4..09af8c54b 100644
--- a/src/Squirrel/UpdateManager.ApplyReleases.cs
+++ b/src/Squirrel/UpdateManager.ApplyReleases.cs
@@ -536,25 +536,25 @@ internal void unshimOurselves()
             // directory are "dead" (i.e. already uninstalled, but not deleted), and
             // we blow them away. This is to make sure that we don't attempt to run
             // an uninstaller on an already-uninstalled version.
-            async Task cleanDeadVersions(SemanticVersion originalVersion, SemanticVersion currentVersion, bool forceUninstall = false)
+            async Task cleanDeadVersions(SemanticVersion currentVersion, SemanticVersion newVersion, bool forceUninstall = false)
             {
-                if (currentVersion == null) return;
+                if (newVersion == null) return;
 
                 var di = new DirectoryInfo(rootAppDirectory);
                 if (!di.Exists) return;
 
-                this.Log().Info("cleanDeadVersions: for version {0}", currentVersion);
-
-                string originalVersionFolder = null;
-                if (originalVersion != null) {
-                    originalVersionFolder = getDirectoryForRelease(originalVersion).Name;
-                    this.Log().Info("cleanDeadVersions: exclude folder {0}", originalVersionFolder);
-                }
+                this.Log().Info("cleanDeadVersions: checking for version {0}", newVersion);
 
                 string currentVersionFolder = null;
                 if (currentVersion != null) {
                     currentVersionFolder = getDirectoryForRelease(currentVersion).Name;
-                    this.Log().Info("cleanDeadVersions: exclude folder {0}", currentVersionFolder);
+                    this.Log().Info("cleanDeadVersions: exclude current version folder {0}", currentVersionFolder);
+                }
+
+                string newVersionFolder = null;
+                if (newVersion != null) {
+                    newVersionFolder = getDirectoryForRelease(newVersion).Name;
+                    this.Log().Info("cleanDeadVersions: exclude new version folder {0}", newVersionFolder);
                 }
 
                 // NB: If we try to access a directory that has already been 
@@ -563,7 +563,7 @@ async Task cleanDeadVersions(SemanticVersion originalVersion, SemanticVersion cu
                 // come from here.
                 var toCleanup = di.GetDirectories()
                     .Where(x => x.Name.ToLowerInvariant().Contains("app-"))
-                    .Where(x => x.Name != currentVersionFolder && x.Name != originalVersionFolder)
+                    .Where(x => x.Name != newVersionFolder && x.Name != currentVersionFolder)
                     .Where(x => !isAppFolderDead(x.FullName));
 
                 if (forceUninstall == false) {
@@ -591,7 +591,7 @@ await squirrelApps.ForEachAsync(async exe => {
                 // Include dead folders in folders to :fire:
                 toCleanup = di.GetDirectories()
                     .Where(x => x.Name.ToLowerInvariant().Contains("app-"))
-                    .Where(x => x.Name != currentVersionFolder && x.Name != originalVersionFolder);
+                    .Where(x => x.Name != newVersionFolder && x.Name != currentVersionFolder);
 
                 // Get the current process list in an attempt to not burn 
                 // directories which have running processes
@@ -625,7 +625,7 @@ await toCleanup.ForEachAsync(async x => {
                 var releaseEntry = default(ReleaseEntry);
 
                 foreach (var entry in entries) {
-                    if (entry.Version == currentVersion) {
+                    if (entry.Version == newVersion) {
                         releaseEntry = ReleaseEntry.GenerateFromFile(Path.Combine(pkgDir, entry.Filename));
                         continue;
                     }
diff --git a/src/Squirrel/UpdateManager.CheckForUpdates.cs b/src/Squirrel/UpdateManager.CheckForUpdates.cs
index 226494d30..9ba91a736 100644
--- a/src/Squirrel/UpdateManager.CheckForUpdates.cs
+++ b/src/Squirrel/UpdateManager.CheckForUpdates.cs
@@ -21,6 +21,7 @@ public CheckForUpdateImpl(string rootAppDirectory)
             }
 
             public async Task<UpdateInfo> CheckForUpdate(
+                UpdaterIntention intention,
                 string localReleaseFile,
                 string updateUrlOrPath,
                 bool ignoreDeltaUpdates = false,
@@ -30,15 +31,19 @@ public async Task<UpdateInfo> CheckForUpdate(
                 progress = progress ?? (_ => { });
 
                 var localReleases = Enumerable.Empty<ReleaseEntry>();
-                var stagingId = getOrCreateStagedUserId();
+                var stagingId = intention == UpdaterIntention.Install ? null : getOrCreateStagedUserId();
 
-                bool shouldInitialize = false;
-                try {
-                    localReleases = Utility.LoadLocalReleases(localReleaseFile);
-                } catch (Exception ex) {
-                    // Something has gone pear-shaped, let's start from scratch
-                    this.Log().WarnException("Failed to load local releases, starting from scratch", ex);
-                    shouldInitialize = true;
+                bool shouldInitialize = intention == UpdaterIntention.Install;
+
+                if (intention != UpdaterIntention.Install) {
+                    try {
+                        localReleases = Utility.LoadLocalReleases(localReleaseFile);
+                    }
+                    catch (Exception ex) {
+                        // Something has gone pear-shaped, let's start from scratch
+                        this.Log().WarnException("Failed to load local releases, starting from scratch", ex);
+                        shouldInitialize = true;
+                    }
                 }
 
                 if (shouldInitialize) await initializeClientAppDirectory();
@@ -125,7 +130,7 @@ public async Task<UpdateInfo> CheckForUpdate(
                     throw new Exception("Remote release File is empty or corrupted");
                 }
 
-                ret = determineUpdateInfo(localReleases, remoteReleases, ignoreDeltaUpdates);
+                ret = determineUpdateInfo(intention, localReleases, remoteReleases, ignoreDeltaUpdates);
 
                 progress(100);
                 return ret;
@@ -142,7 +147,7 @@ async Task initializeClientAppDirectory()
                 Directory.CreateDirectory(pkgDir);
             }
 
-            UpdateInfo determineUpdateInfo(IEnumerable<ReleaseEntry> localReleases, IEnumerable<ReleaseEntry> remoteReleases, bool ignoreDeltaUpdates)
+            UpdateInfo determineUpdateInfo(UpdaterIntention intention, IEnumerable<ReleaseEntry> localReleases, IEnumerable<ReleaseEntry> remoteReleases, bool ignoreDeltaUpdates)
             {
                 var packageDirectory = Utility.PackageDirectoryForAppDir(rootAppDirectory);
                 localReleases = localReleases ?? Enumerable.Empty<ReleaseEntry>();
@@ -167,7 +172,12 @@ UpdateInfo determineUpdateInfo(IEnumerable<ReleaseEntry> localReleases, IEnumera
                 }
 
                 if (!localReleases.Any()) {
-                    this.Log().Warn("First run or local directory is corrupt, starting from scratch");
+                    if (intention == UpdaterIntention.Install) {
+                        this.Log().Info("First run, starting from scratch");
+                    } else {
+                        this.Log().Warn("No local releases found, starting from scratch");
+                    }
+
                     return UpdateInfo.Create(null, new[] {latestFullRelease}, packageDirectory);
                 }
 
diff --git a/src/Squirrel/UpdateManager.cs b/src/Squirrel/UpdateManager.cs
index 6e9d59f59..9f96e773e 100644
--- a/src/Squirrel/UpdateManager.cs
+++ b/src/Squirrel/UpdateManager.cs
@@ -49,12 +49,12 @@ public UpdateManager(string urlOrPath,
             this.rootAppDirectory = Path.Combine(rootDirectory ?? GetLocalAppDataDirectory(), this.applicationName);
         }
 
-        public async Task<UpdateInfo> CheckForUpdate(bool ignoreDeltaUpdates = false, Action<int> progress = null)
+        public async Task<UpdateInfo> CheckForUpdate(bool ignoreDeltaUpdates = false, Action<int> progress = null, UpdaterIntention intention = UpdaterIntention.Update)
         {
             var checkForUpdate = new CheckForUpdateImpl(rootAppDirectory);
 
             await acquireUpdateLock();
-            return await checkForUpdate.CheckForUpdate(Utility.LocalReleaseFileForAppDir(rootAppDirectory), updateUrlOrPath, ignoreDeltaUpdates, progress, urlDownloader);
+            return await checkForUpdate.CheckForUpdate(intention, Utility.LocalReleaseFileForAppDir(rootAppDirectory), updateUrlOrPath, ignoreDeltaUpdates, progress, urlDownloader);
         }
 
         public async Task DownloadReleases(IEnumerable<ReleaseEntry> releasesToDownload, Action<int> progress = null)
@@ -75,7 +75,7 @@ public async Task<string> ApplyReleases(UpdateInfo updateInfo, Action<int> progr
 
         public async Task FullInstall(bool silentInstall = false, Action<int> progress = null)
         {
-            var updateInfo = await CheckForUpdate();
+            var updateInfo = await CheckForUpdate(intention: UpdaterIntention.Install);
             await DownloadReleases(updateInfo.ReleasesToApply);
 
             var applyReleases = new ApplyReleasesImpl(rootAppDirectory);
diff --git a/src/Update/Program.cs b/src/Update/Program.cs
index 6c23be6e1..d9a0af72b 100644
--- a/src/Update/Program.cs
+++ b/src/Update/Program.cs
@@ -1,4 +1,7 @@
-using System;
+using NuGet;
+using Splat;
+using Squirrel.Json;
+using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Globalization;
@@ -7,13 +10,9 @@
 using System.Linq;
 using System.Reflection;
 using System.Text;
+using System.Text.RegularExpressions;
 using System.Threading;
 using System.Threading.Tasks;
-using Mono.Options;
-using Splat;
-using Squirrel.Json;
-using NuGet;
-using System.Text.RegularExpressions;
 
 namespace Squirrel.Update
 {
@@ -24,7 +23,7 @@ enum UpdateAction {
 
     class Program : IEnableLogger
     {
-        static OptionSet opts;
+        static StartupOption opt;
 
         public static int Main(string[] args)
         {
@@ -41,17 +40,27 @@ public static int Main(string[] args)
 
         int main(string[] args)
         {
+            try {
+                opt = new StartupOption(args);
+            } catch (Exception ex) {
+                using (var logger = new SetupLogLogger(true, "OptionParsing") { Level = LogLevel.Info }) {
+                    Locator.CurrentMutable.Register(() => logger, typeof(Splat.ILogger));
+                    logger.Write($"Failed to parse command line options. {ex.Message}", LogLevel.Error);
+                }
+                throw;
+            }
+
             // NB: Trying to delete the app directory while we have Setup.log
             // open will actually crash the uninstaller
-            bool isUninstalling = args.Any(x => x.Contains("uninstall"));
+            bool isUninstalling = opt.updateAction == UpdateAction.Uninstall;
 
-            using (var logger = new SetupLogLogger(isUninstalling) {Level = LogLevel.Info}) {
+            using (var logger = new SetupLogLogger(isUninstalling, opt.updateAction.ToString()) {Level = LogLevel.Info}) {
                 Locator.CurrentMutable.Register(() => logger, typeof (Splat.ILogger));
 
                 try {
                     return executeCommandLine(args);
                 } catch (Exception ex) {
-                    logger.Write("Unhandled exception: " + ex, LogLevel.Fatal);
+                    logger.Write("Finished with unhandled exception: " + ex, LogLevel.Fatal);
                     throw;
                 }
             }
@@ -81,116 +90,53 @@ int executeCommandLine(string[] args)
                     return 0;
                 }
 
-                bool silentInstall = false;
-                var updateAction = default(UpdateAction);
-
-                string target = default(string);
-                string releaseDir = default(string);
-                string packagesDir = default(string);
-                string bootstrapperExe = default(string);
-                string backgroundGif = default(string);
-                string signingParameters = default(string);
-                string baseUrl = default(string);
-                string processStart = default(string);
-                string processStartArgs = default(string);
-                string setupIcon = default(string);
-                string icon = default(string);
-                string shortcutArgs = default(string);
-                string frameworkVersion = "net45";
-                bool shouldWait = false;
-                bool noMsi = (Environment.OSVersion.Platform != PlatformID.Win32NT);        // NB: WiX doesn't work under Mono / Wine
-                bool noDelta = false;
-                bool packageAs64Bit = false;
-
-                opts = new OptionSet() {
-                    "Usage: Squirrel.exe command [OPTS]",
-                    "Manages Squirrel packages",
-                    "",
-                    "Commands",
-                    { "install=", "Install the app whose package is in the specified directory", v => { updateAction = UpdateAction.Install; target = v; } },
-                    { "uninstall", "Uninstall the app the same dir as Update.exe", v => updateAction = UpdateAction.Uninstall},
-                    { "download=", "Download the releases specified by the URL and write new results to stdout as JSON", v => { updateAction = UpdateAction.Download; target = v; } },
-                    { "checkForUpdate=", "Check for one available update and writes new results to stdout as JSON", v => { updateAction = UpdateAction.CheckForUpdate; target = v; } },
-                    { "update=", "Update the application to the latest remote version specified by URL", v => { updateAction = UpdateAction.Update; target = v; } },
-                    { "releasify=", "Update or generate a releases directory with a given NuGet package", v => { updateAction = UpdateAction.Releasify; target = v; } },
-                    { "createShortcut=", "Create a shortcut for the given executable name", v => { updateAction = UpdateAction.Shortcut; target = v; } },
-                    { "removeShortcut=", "Remove a shortcut for the given executable name", v => { updateAction = UpdateAction.Deshortcut; target = v; } },
-                    { "updateSelf=", "Copy the currently executing Update.exe into the default location", v => { updateAction =  UpdateAction.UpdateSelf; target = v; } },
-                    { "processStart=", "Start an executable in the latest version of the app package", v => { updateAction =  UpdateAction.ProcessStart; processStart = v; }, true},
-                    { "processStartAndWait=", "Start an executable in the latest version of the app package", v => { updateAction =  UpdateAction.ProcessStart; processStart = v; shouldWait = true; }, true},
-                    "",
-                    "Options:",
-                    { "h|?|help", "Display Help and exit", _ => {} },
-                    { "r=|releaseDir=", "Path to a release directory to use with releasify", v => releaseDir = v},
-                    { "p=|packagesDir=", "Path to the NuGet Packages directory for C# apps", v => packagesDir = v},
-                    { "bootstrapperExe=", "Path to the Setup.exe to use as a template", v => bootstrapperExe = v},
-                    { "g=|loadingGif=", "Path to an animated GIF to be displayed during installation", v => backgroundGif = v},
-                    { "i=|icon", "Path to an ICO file that will be used for icon shortcuts", v => icon = v},
-                    { "setupIcon=", "Path to an ICO file that will be used for the Setup executable's icon", v => setupIcon = v},
-                    { "n=|signWithParams=", "Sign the installer via SignTool.exe with the parameters given", v => signingParameters = v},
-                    { "s|silent", "Silent install", _ => silentInstall = true},
-                    { "b=|baseUrl=", "Provides a base URL to prefix the RELEASES file packages with", v => baseUrl = v, true},
-                    { "a=|process-start-args=", "Arguments that will be used when starting executable", v => processStartArgs = v, true},
-                    { "l=|shortcut-locations=", "Comma-separated string of shortcut locations, e.g. 'Desktop,StartMenu'", v => shortcutArgs = v},
-                    { "no-msi", "Don't generate an MSI package", v => noMsi = true},
-                    { "no-delta", "Don't generate delta packages to save time", v => noDelta = true},
-                    { "framework-version=", "Set the required .NET framework version, e.g. net461", v => frameworkVersion = v },
-                    { "msi-win64", "Mark the MSI as 64-bit, which is useful in Enterprise deployment scenarios", _ => packageAs64Bit = true},
-                };
-
-                opts.Parse(args);
-
-                // NB: setupIcon and icon are just aliases for compatibility
-                // reasons, because of a dumb breaking rename I made in 1.0.1
-                setupIcon = setupIcon ?? icon;
-
-                if (updateAction == UpdateAction.Unset) {
+                if (opt.updateAction == UpdateAction.Unset) {
                     ShowHelp();
                     return -1;
                 }
 
-                switch (updateAction) {
+                switch (opt.updateAction) {
 #if !MONO
                 case UpdateAction.Install:
                     var progressSource = new ProgressSource();
-                    if (!silentInstall) {
+                    if (!opt.silentInstall) {
                         AnimatedGifWindow.ShowWindow(TimeSpan.FromSeconds(4), animatedGifWindowToken.Token, progressSource);
                     }
 
-                    Install(silentInstall, progressSource, Path.GetFullPath(target)).Wait();
+                    Install(opt.silentInstall, progressSource, Path.GetFullPath(opt.target)).Wait();
                     animatedGifWindowToken.Cancel();
                     break;
                 case UpdateAction.Uninstall:
                     Uninstall().Wait();
                     break;
                 case UpdateAction.Download:
-                    Console.WriteLine(Download(target).Result);
+                    Console.WriteLine(Download(opt.target).Result);
                     break;
                 case UpdateAction.Update:
-                    Update(target).Wait();
+                    Update(opt.target).Wait();
                     break;
                 case UpdateAction.CheckForUpdate:
-                    Console.WriteLine(CheckForUpdate(target).Result);
+                    Console.WriteLine(CheckForUpdate(opt.target).Result);
                     break;
                 case UpdateAction.UpdateSelf:
                     UpdateSelf().Wait();
                     break;
                 case UpdateAction.Shortcut:
-                    Shortcut(target, shortcutArgs, processStartArgs, setupIcon);
+                    Shortcut(opt.target, opt.shortcutArgs, opt.processStartArgs, opt.setupIcon);
                     break;
                 case UpdateAction.Deshortcut:
-                    Deshortcut(target, shortcutArgs);
+                    Deshortcut(opt.target, opt.shortcutArgs);
                     break;
                 case UpdateAction.ProcessStart:
-                    ProcessStart(processStart, processStartArgs, shouldWait);
+                    ProcessStart(opt.processStart, opt.processStartArgs, opt.shouldWait);
                     break;
 #endif
                 case UpdateAction.Releasify:
-                    Releasify(target, releaseDir, packagesDir, bootstrapperExe, backgroundGif, signingParameters, baseUrl, setupIcon, !noMsi, packageAs64Bit, frameworkVersion, !noDelta);
+                    Releasify(opt.target, opt.releaseDir, opt.packagesDir, opt.bootstrapperExe, opt.backgroundGif, opt.signingParameters, opt.baseUrl, opt.setupIcon, !opt.noMsi, opt.packageAs64Bit, opt.frameworkVersion, !opt.noDelta);
                     break;
                 }
             }
-
+            this.Log().Info("Finished Squirrel Updater");
             return 0;
         }
 
@@ -253,7 +199,7 @@ public async Task Update(string updateUrl, string appName = null)
 
             retry:
                 try {
-                    var updateInfo = await mgr.CheckForUpdate(ignoreDeltaUpdates: ignoreDeltaUpdates, progress: x => Console.WriteLine(x / 3));
+                    var updateInfo = await mgr.CheckForUpdate(intention: UpdaterIntention.Update, ignoreDeltaUpdates: ignoreDeltaUpdates, progress: x => Console.WriteLine(x / 3));
                     await mgr.DownloadReleases(updateInfo.ReleasesToApply, x => Console.WriteLine(33 + x / 3));
                     await mgr.ApplyReleases(updateInfo, x => Console.WriteLine(66 + x / 3));
                 } catch (Exception ex) {
@@ -294,7 +240,7 @@ public async Task<string> Download(string updateUrl, string appName = null)
 
             this.Log().Info("Fetching update information, downloading from " + updateUrl);
             using (var mgr = new UpdateManager(updateUrl, appName)) {
-                var updateInfo = await mgr.CheckForUpdate(progress: x => Console.WriteLine(x / 3));
+                var updateInfo = await mgr.CheckForUpdate(intention: UpdaterIntention.Update, progress: x => Console.WriteLine(x / 3));
                 await mgr.DownloadReleases(updateInfo.ReleasesToApply, x => Console.WriteLine(33 + x / 3));
 
                 var releaseNotes = updateInfo.FetchReleaseNotes();
@@ -318,7 +264,7 @@ public async Task<string> CheckForUpdate(string updateUrl, string appName = null
 
             this.Log().Info("Fetching update information, downloading from " + updateUrl);
             using (var mgr = new UpdateManager(updateUrl, appName)) {
-                var updateInfo = await mgr.CheckForUpdate(progress: x => Console.WriteLine(x));
+                var updateInfo = await mgr.CheckForUpdate(intention: UpdaterIntention.Update, progress: x => Console.WriteLine(x));
                 var releaseNotes = updateInfo.FetchReleaseNotes();
 
                 var sanitizedUpdateInfo = new {
@@ -561,7 +507,7 @@ public void ProcessStart(string exeName, string arguments, bool shouldWait)
         public void ShowHelp()
         {
             ensureConsole();
-            opts.WriteOptionDescriptions(Console.Out);
+            opt.WriteOptionDescriptions();
         }
 
         void waitForParentToExit()
@@ -865,16 +811,16 @@ class SetupLogLogger : Splat.ILogger, IDisposable
         readonly object gate = 42;
         public Splat.LogLevel Level { get; set; }
 
-        public SetupLogLogger(bool saveInTemp)
+        public SetupLogLogger(bool saveInTemp, string commandSuffix = null)
         {
             for (int i=0; i < 10; i++) {
                 try {
                     var dir = saveInTemp ?
                         Path.GetTempPath() :
                         Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
-
-                    var file = Path.Combine(dir, String.Format("SquirrelSetup.{0}.log", i).Replace(".0.log", ".log"));
-                    var str = File.Open(file, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
+                    var fileName = commandSuffix == null ? String.Format($"Squirrel.{i}.log", i) : String.Format($"Squirrel-{commandSuffix}.{i}.log", i);
+                    var file = Path.Combine(dir, fileName.Replace(".0.log", ".log"));
+                    var str = File.Open(file, FileMode.Append, FileAccess.Write, FileShare.Read);
                     inner = new StreamWriter(str, Encoding.UTF8, 4096, false) { AutoFlush = true };
                     return;
                 } catch (Exception ex) {
@@ -892,7 +838,7 @@ public void Write(string message, LogLevel logLevel)
                 return;
             }
 
-            lock (gate) inner.WriteLine("{0}> {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), message);
+            lock (gate) inner.WriteLine($"[{DateTime.Now.ToString("dd/MM/yy HH:mm:ss")}] {logLevel.ToString().ToLower()}: {message}");
         }
 
         public void Dispose()
diff --git a/src/Update/StartupOption.cs b/src/Update/StartupOption.cs
new file mode 100644
index 000000000..379c1ac17
--- /dev/null
+++ b/src/Update/StartupOption.cs
@@ -0,0 +1,85 @@
+using Mono.Options;
+using System;
+
+namespace Squirrel.Update
+{
+    internal class StartupOption
+    {
+        private readonly OptionSet optionSet;
+
+        internal bool silentInstall { get; private set; } = false;
+        internal UpdateAction updateAction { get; private set; } = default(UpdateAction);
+        internal string target { get; private set; } = default(string);
+        internal string releaseDir { get; private set; } = default(string);
+        internal string packagesDir { get; private set; } = default(string);
+        internal string bootstrapperExe { get; private set; } = default(string);
+        internal string backgroundGif { get; private set; } = default(string);
+        internal string signingParameters { get; private set; } = default(string);
+        internal string baseUrl { get; private set; } = default(string);
+        internal string processStart { get; private set; } = default(string);
+        internal string processStartArgs { get; private set; } = default(string);
+        internal string setupIcon { get; private set; } = default(string);
+        internal string icon { get; private set; } = default(string);
+        internal string shortcutArgs { get; private set; } = default(string);
+        internal string frameworkVersion { get; private set; } = "net45";
+        internal bool shouldWait { get; private set; } = false;
+        internal bool noMsi { get; private set; } = (Environment.OSVersion.Platform != PlatformID.Win32NT);        // NB: WiX doesn't work under Mono / Wine
+        internal bool packageAs64Bit { get; private set; } = false;
+        internal bool noDelta { get; private set; } = false;
+               
+        public StartupOption(string[] args) {
+           optionSet = Parse(args);
+        }
+
+        private OptionSet Parse(string[] args) {
+            var opts = new OptionSet() {
+                "Usage: Squirrel.exe command [OPTS]",
+                "Manages Squirrel packages",
+                "",
+                "Commands",
+                { "install=", "Install the app whose package is in the specified directory", v => { updateAction = UpdateAction.Install; target = v; } },
+                { "uninstall", "Uninstall the app the same dir as Update.exe", v => updateAction = UpdateAction.Uninstall},
+                { "download=", "Download the releases specified by the URL and write new results to stdout as JSON", v => { updateAction = UpdateAction.Download; target = v; } },
+                { "checkForUpdate=", "Check for one available update and writes new results to stdout as JSON", v => { updateAction = UpdateAction.CheckForUpdate; target = v; } },
+                { "update=", "Update the application to the latest remote version specified by URL", v => { updateAction = UpdateAction.Update; target = v; } },
+                { "releasify=", "Update or generate a releases directory with a given NuGet package", v => { updateAction = UpdateAction.Releasify; target = v; } },
+                { "createShortcut=", "Create a shortcut for the given executable name", v => { updateAction = UpdateAction.Shortcut; target = v; } },
+                { "removeShortcut=", "Remove a shortcut for the given executable name", v => { updateAction = UpdateAction.Deshortcut; target = v; } },
+                { "updateSelf=", "Copy the currently executing Update.exe into the default location", v => { updateAction =  UpdateAction.UpdateSelf; target = v; } },
+                { "processStart=", "Start an executable in the latest version of the app package", v => { updateAction =  UpdateAction.ProcessStart; processStart = v; }, true},
+                { "processStartAndWait=", "Start an executable in the latest version of the app package", v => { updateAction =  UpdateAction.ProcessStart; processStart = v; shouldWait = true; }, true},
+                "",
+                "Options:",
+                { "h|?|help", "Display Help and exit", _ => {} },
+                { "r=|releaseDir=", "Path to a release directory to use with releasify", v => releaseDir = v},
+                { "p=|packagesDir=", "Path to the NuGet Packages directory for C# apps", v => packagesDir = v},
+                { "bootstrapperExe=", "Path to the Setup.exe to use as a template", v => bootstrapperExe = v},
+                { "g=|loadingGif=", "Path to an animated GIF to be displayed during installation", v => backgroundGif = v},
+                { "i=|icon", "Path to an ICO file that will be used for icon shortcuts", v => icon = v},
+                { "setupIcon=", "Path to an ICO file that will be used for the Setup executable's icon", v => setupIcon = v},
+                { "n=|signWithParams=", "Sign the installer via SignTool.exe with the parameters given", v => signingParameters = v},
+                { "s|silent", "Silent install", _ => silentInstall = true},
+                { "b=|baseUrl=", "Provides a base URL to prefix the RELEASES file packages with", v => baseUrl = v, true},
+                { "a=|process-start-args=", "Arguments that will be used when starting executable", v => processStartArgs = v, true},
+                { "l=|shortcut-locations=", "Comma-separated string of shortcut locations, e.g. 'Desktop,StartMenu'", v => shortcutArgs = v},
+                { "no-msi", "Don't generate an MSI package", v => noMsi = true},
+                { "no-delta", "Don't generate delta packages to save time", v => noDelta = true},
+                { "framework-version=", "Set the required .NET framework version, e.g. net461", v => frameworkVersion = v },
+                { "msi-win64", "Mark the MSI as 64-bit, which is useful in Enterprise deployment scenarios", _ => packageAs64Bit = true},
+            };
+
+            opts.Parse(args);
+
+            // NB: setupIcon and icon are just aliases for compatibility
+            // reasons, because of a dumb breaking rename I made in 1.0.1
+            setupIcon = setupIcon ?? icon;
+
+            return opts;
+        }
+
+        internal void WriteOptionDescriptions() {
+            optionSet.WriteOptionDescriptions(Console.Out);
+        }
+    }
+}
+
diff --git a/src/Update/Update-Mono.csproj b/src/Update/Update-Mono.csproj
index f26ae6c3d..f7330bc2b 100644
--- a/src/Update/Update-Mono.csproj
+++ b/src/Update/Update-Mono.csproj
@@ -82,6 +82,7 @@
     <Compile Include="Mono.Options\Options.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="StartupOption.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="App.config" />
diff --git a/src/Update/Update.csproj b/src/Update/Update.csproj
index 788bdab97..fe176f29c 100644
--- a/src/Update/Update.csproj
+++ b/src/Update/Update.csproj
@@ -83,6 +83,7 @@
     <Compile Include="Mono.Options\Options.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="StartupOption.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="App.config" />
@@ -130,4 +131,4 @@ ren "$(TargetFileName).tmp" "$(TargetFileName)"</PostBuildEvent>
   <Target Name="AfterBuild">
   </Target>
   -->
-</Project>
+</Project>
\ No newline at end of file