@todesktop/cli

    1.2.2 • Public • Published

    ToDesktop CLI

    The ToDesktop CLI allows you to build and deploy your electron app with native installers, auto-updates and code signing included.

    For more information, visit the project landing page.

    Table of contents

    Installation

    Install the package with:

    npm install --location=global @todesktop/cli
    # or
    yarn global add @todesktop/cli

    Get started

    You can use the ToDesktop CLI to work with an Electron application in 4 steps:

    Step 1: Create a ToDesktop application

    Create a ToDesktop application to link to your Electron application. This is currently done via the web interface. Copy the ToDesktop application ID to your clipboard:

    ToDesktop ID

    Step 2: Setup your todesktop.json file

    Create a todesktop.json file in the root of your Electron project.

    {
      "id": "your-todesktop-id",
      "icon": "./desktop-icon.png",
      "schemaVersion": 1
    }

    See Project configuration for the full list of configuration options.

    Step 3: Add @todesktop/runtime as a dependency

    The ToDesktop runtime package takes care of auto-updating, crash reporting, and more.

    npm install @todesktop/runtime
    # or
    yarn add @todesktop/runtime

    In your main (background process) script, require the package and call the init function. The key is to call it right at the beginning.

    const { app, BrowserWindow } = require("electron");
    const todesktop = require("@todesktop/runtime");
    
    todesktop.init();
    
    function createWindow() {
      // Create the browser window.
      let win = new BrowserWindow({
        width: 800,
        height: 600,
      });
    
      // and load the index.html of the app.
      win.loadFile("index.html");
    }
    
    app.whenReady().then(createWindow);

    Step 4: Build your app

    To build your app, run the following command inside the root of your Electron project:

    todesktop build

    When prompted to login, use the email address and accessToken we would have provided you with. As this is in active beta, contact us if you do not yet have these credentials.

    You app can then be downloaded and tested.

    Step 5: Release your app

    To release that build (i.e. publish new downloads and an auto-update), run:

    todesktop release

    See the next section for more information on the available commands.

    CLI Commands

    The main command:

    todesktop build

    This builds your Electron app with native installers, code signing, and so on baked-in. Once the build has succeeded, you should see the following output in your terminal. These are links to the download binaries for each platform:

    > ✅ ToDesktop Quick Start v1.0.0
    > Build complete!
    > https://dl.todesktop.com/200301s7gg0kd5i/builds/sdsdf23
    
    >See web UI for more information:
    >https://app.todesktop.com/apps/200301s7gg0kd5i/builds/sdsdf23

    We also support:

    • todesktop build --code-sign=false. Run a build with code-signing and notarization disabled. This is handy for testing builds quickly.
    • todesktop release. Release a build. This will publish a new download and an auto-update for existing users. By default it shows a list of builds for you to choose from.
      • Use todesktop release <id> to release a specific build by ID.
      • todesktop release --latest will release the latest build.
      • Append --force to skip the interactive confirmation step.
    • todesktop builds. View your recent builds.
      • Use todesktop builds <id> to view a specific build and its progress.
      • todesktop builds --latest will show the latest build and it's progress.
    • todesktop logout. Logs you out.
    • todesktop whoami. Prints the email of the account you're signed into.
    • todesktop --help. Shows the help documentation.
    • todesktop --version. Shows the current version of the CLI.

    Automating your builds (CI)

    You may want to automate builds with your Continuous Integration (CI) provider. To achieve this, simply set up environment variables for TODESKTOP_ACCESS_TOKEN and TODESKTOP_EMAIL within your CI project.

    TODESKTOP_ACCESS_TOKEN=accessToken
    TODESKTOP_EMAIL=email
    

    To build and release in one step, you can execute:

    todesktop build && todesktop release --latest --force

    Project configuration (todesktop.json)

    This describes all of the possible configuration options ín your todesktop.json.

    To avoid confusion, the following terms will be used throughout this file:

    • "Project root": this is the parent directory of your todesktop.json.

    appFiles - (optional) array of glob patterns

    Default: ["**"]

    Example: ["dist/**", "!static/**"]

    This option allows you to decide which files get uploaded to be built on the ToDesktop servers. By default, all files in your app path are included in your app, except for node_modules and .git. Dependencies are installed on our build servers as there could be platform-specific postinstall steps.

    If you wish to include files for the build process but exclude them in the distribtion version of your app then you should use the filesForDistribution property

    The files must be within your appPath.

    The following are always included if they exist:

    • /package.json
    • /package-lock.json
    • /yarn.lock
    • /pnpm-lock.yaml
    • /shrinkwrap.yaml

    Pattern syntax

    • Asterisk (*) — matches everything except slashes (path separators).
    • A double star or globstar (**) — matches zero or more directories.
    • Question mark (?) – matches any single character except slashes (path separators).
    • Exclamation mark (!) — a glob that starts with an exclamation mark will result in any matched files being excluded.

    Examples:

    • src/**/*.js — matches all files in the src directory (any level of nesting) that have the .js extension.
    • src/*.?? — matches all files in the src directory (only first level of nesting) that have a two-character extension.

    We use the fast-glob library under the hood.

    appId - (optional) string

    Default: auto-generated.

    Example: com.microsoft.word.

    Your application ID. Omit this unless you know what you're doing. It's used as the CFBundleIdentifier for MacOS and as the Application User Model ID for Windows.

    WARNING: if you have deployed an application with ToDesktop and would like to change this ID, talk to us first.

    appPath - (optional) string

    Default: ..

    Example: ./dist.

    This is the path to your Electron application directory. Omit this unless your project setup is complicated. This is the directory that the CLI uploads.

    The path can be absolute or a relative path from the project root. The directory it points to must be a valid Electron application directory; i.e.:

    • It could be ran with the electron command; i.e. npx electron {{appPath}}.
    • It needs to contain a valid package.json.
    • The package.json must either have a main property pointing to a file in the directory or there must be an index.js at the root of the directory.

    Side note: if your package.json contains a postinstall script which references scripts, these must be accessible within the appPath directory as only the appPath is uploaded to our servers.

    appProtocolScheme - (optional) string

    Default: no protocol scheme is registered.

    Example: word.

    If you want to register a protocol for your application (e.g. example://) and or support deeplinking, you will need to use this option. If your desired protocol is example://, you would set "appProtocolScheme": "example". NOTE: these features also require additional application logic.

    asarUnpack - (optional) boolean or array of glob patterns

    Default: [**/*.node]

    This option allows you to decide which files get unpacked from the asar archive. By default we unpack all native *.node files.

    If you want to unpack only files that are required to be unpacked, you can set this property to false.

    You can also specify a list of glob patterns to unpack.

    copyright - (optional) string

    Default: The package.json productName / name.

    Example: Copyright © 1995 Walt Disney.

    The human-readable copyright line for the app.

    dmg - (optional) object

    dmg.background - (optional) string

    Example: ./mac-dmg-background.tiff.

    Default: undefined (if undefined then we use this template).

    The path to the DMG installer's background image. It must be a .tiff file. The resolution of this file determines the resolution of the installer window. Typically, backgrounds are 540x380.

    You can generate a retina tiff background from png files using the following command:

    tiffutil -cathidpicheck background.png background@2x.png -out background.tiff

    dmg.backgroundColor - (optional) string

    The background color (accepts css colors). Defaults to "#ffffff" (white) if no background image.

    dmg.iconSize - (optional) number

    The size of all the icons inside the DMG. Defaults to 80.

    dmg.iconTextSize - (optional) number

    The size of all the icon texts inside the DMG. Defaults to 12.

    dmg.title - (optional) string

    The title of the produced DMG, which will be shown when mounted (volume name). Macro ${productName}, ${version} and ${name} are supported.

    Defaults to "${productName} ${version}".

    dmg.contents - (optional) Array of objects

    Customize icon locations. The x and y coordinates refer to the position of the center of the icon (at 1x scale), and do not take the label into account.

    • x number - The device-independent pixel offset from the left of the window to the center of the icon.
    • y number - The device-independent pixel offset from the top of the window to the center of the icon.
    [
      {
        // Your app icon
        "x": 100,
        "y": 100
      },
      {
        // Applications directory icon
        "x": 300,
        "y": 100,
      }
    ]
    

    dmg.window - (optional) object

    The DMG windows position and size. In most cases, you will only want to specify a height and width value but not x and y.

    • x number - The X position relative to left of the screen.
    • y number - The Y position relative to top of the screen.
    • width number - The width. Defaults to background image width or 540.
    • height number - The height. Defaults to background image height or 380.
    {
      "width": "400",
      "height": "300"
    }
    

    extraContentFiles - (optional) array of objects

    Default: [].

    This option allows you specify files to be copied into the application's content directory (Contents for MacOS, root directory for Linux and Windows).

    Each item in the array must be an object, containing a from property which is a path to a file or directory. The path can be absolute or a relative path from the project root. The files specified must be inside your project root. A directory's contents are copied, not the directory itself (see example below).

    The to property is optional. Use it to specify a directory inside the content directory to copy the file to.

    Example:

    [
      { "from": "./static/image.png" },
      { "from": "./static/other/anotherImage.png", "to": "images" },
      { "from": "./static", "to": "assets" }
    ]

    In the example above, image.png would be copied to the root of the content directory, whereas anotherImage.png would be copied to an images directory at the root of the content directory. The contents of the ./static directory would be copied to assets in the content directory (i.e. ./static/example.txt would be copied to assets/example.txt).

    electronMirror - (optional) string

    Default: Electron is downloaded from the main official source.

    Example: https://cdn.npm.taobao.org/dist/electron/

    The base URL of the mirror to download Electron from. This may be a mirror geographically closer to you or even your own mirror which contains custom Electron builds. The version downloaded is the Electron version specified in devDependencies in your app's package.json. Alternatively you can explicitly specify an electronVersion in todesktop.json as described below.

    electronVersion - (optional) string

    Default: Electron version specified in devDependencies in your app's package.json

    Example: 12.0.7-beta.17

    The version of Electron to use. In most cases you should not specify an electronVersion property. Only specify this option if you wish to override the version that is specified in package.json.

    extraResources - (optional) array of objects

    Default: [].

    Example:

    [
      { "from": "./static/image.png" },
      { "from": "./static/other/anotherImage.png", "to": "images" },
      { "from": "./static", "to": "assets" }
    ]

    This option allows you to specify files to be copied into the application's resources directory (Contents/Resources for MacOS, resources for Linux and Windows). It works just like the extraContentFiles option, except the files go to a different directory.

    fileAssociations - (optional) array of objects

    Associate a file type with your Electron app.

    Example:

    [
      {
        "ext": "ics",
        "name": "Calendar"
      }
    ]
    • ext String | Array - The extension (minus the leading period). e.g. png.
    • name String - The name. e.g. PNG. Defaults to value of ext.
    • description String - windows-only. The description.
    • mimeType String - linux-only. The mime-type.
    • role = Editor String - macOS-only The app’s role with respect to the type. The value can be Editor, Viewer, Shell, or None. Corresponds to CFBundleTypeRole.
    • isPackage Boolean - macOS-only Whether the document is distributed as a bundle. If set to true, the bundle directory is treated as a file. Corresponds to LSTypeIsPackage.

    filesForDistribution - (optional) array of glob patterns

    Example: ["!**/node_modules/realm/android/**", "!**/design/**"]

    This option allows you to explicitly exclude or include certain files in the packaged version of your app. These files are filtered after the build step which happens on the ToDesktop servers.

    This is often useful for excluding large files which are installed during the build step but are not needed at runtime by your applcation.

    The following are always excluded if they exist:

    • !**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme}
    • !**/node_modules/*/{test,__tests__,tests,powered-test,example,examples}
    • !**/node_modules/*.d.ts
    • !**/node_modules/.bin
    • !**/*.{iml,o,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,xproj}
    • !.editorconfig
    • !**/._*
    • !**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,.gitignore,.gitattributes}
    • !**/{__pycache__,thumbs.db,.flowconfig,.idea,.vs,.nyc_output}
    • !**/{appveyor.yml,.travis.yml,circle.yml}
    • !**/{npm-debug.log,yarn.lock,.yarn-integrity,.yarn-metadata.json}

    icon - string

    Example: ./appIcon.png.

    The path to your application's desktop icon. It must be an ICNS or PNG.

    Note: to ensure the icon is never missing (e.g. this happens sometimes in Ubuntu), set the icon option when creating your BrowserWindows.

    id - string

    Example: 2005223bd1nqpl7

    Your ToDesktop application ID. This is used to identify your app. This would have been generated when you first created your ToDesktop application via the web interface:

    ToDesktop ID

    linux - (optional) object

    Default: We have good default settings for Linux.

    Example: { "category": "Utility".

    This object contains some options that only apply to the building & releasing for Linux.

    linux.category - (optional) string

    Default: undefined

    Example: Utility.

    The application category.

    linux.icon - (optional) string

    Example: ./linux-icon.png.

    Default: The root icon is used.

    The path to your application's Linux desktop icon. It must be an ICNS or PNG.

    Note: to ensure the icon is never missing (e.g. this happens sometimes in Ubuntu), set the icon option when creating your BrowserWindows.

    linux.noSandbox - (optional) boolean

    Default: true

    This option allows you to configure whether your app should run in a sandboxed environment.

    We default this to true for compatibility reasons because some Linux distributions do not support unprivileged user namespaces.

    mac - (optional) object

    Default: We have good default settings for Mac. Example: { "entitlements": "./entitlements.mac.plist".

    This object contains some options that only apply to the building & releasing for MacOS.

    mac.additionalBinariesToSign - (optional) array of strings

    Default: [] Example: ["./node_modules/example-package/example-file"].

    Paths of any extra binaries that need to be signed. These could be files in your own app code or node_modules.

    mac.category - (optional) string

    Default: undefined Example: public.app-category.productivity.

    The application category type, as shown in the Finder via View -> Arrange by Application Category when viewing the Applications directory.

    For example, public.app-category.developer-tools will set the application category to "Developer Tools".

    Valid values are listed in Apple’s documentation.

    mac.entitlements - (optional) string

    Default: A sane minimal entitlements file we've put together. Example: ./entitlements.mac.plist.

    The path to an entitlements file for signing your application. It must be a plist file.

    mac.extendInfo - (optional) object

    Default: {}. Example: { "NSUserNotificationAlertStyle": "alert" }.

    Extra entries for Info.plist.

    mac.icon - (optional) string

    Example: ./mac-icon.png.

    Default: The root icon is used.

    The path to your application's Mac desktop icon. It must be an ICNS or PNG.

    schemaVersion - number

    Example: 1.

    This is the todesktop.json schema version. This must be 1.

    snap - (optional) object

    Example: { "confinement": "classic", "grade": "devel" }.

    This object contains some options that only apply to the building for the Snap Store.

    snap.after - (optional) array of strings

    Default: ["desktop-gtk2"].

    Example: ["launch-scripts"].

    Ensures that all the part names listed are staged before the app part begins its lifecycle.

    snap.appPartStage - (optional) array of strings

    Default: See snap.ts.

    Example: ["-usr/lib/python*"].

    Specifies which files from the app part to stage and which to exclude. Individual files, directories, wildcards, globstars, and exclusions are accepted. See Snapcraft filesets to learn more about the format.

    snap.assumes - (optional) string or array of strings

    Default: undefined.

    Example: snapd2.38.

    The list of features that must be supported by the core in order for this snap to install. To learn more, see the Snapcraft docs.

    snap.autoStart - (optional) boolean

    Default: false.

    Example: true.

    Whether or not the snap should automatically start on login.

    snap.buildPackages - (optional) array of strings

    Default: [].

    Example: ["libssl-dev", "libssh-dev", "libncursesw5-dev"].

    The list of debian packages needs to be installed for building this snap.

    snap.confinement - (optional) string

    Default: strict.

    Example: classic.

    The type of confinement supported by the snap. devmode, strict, or classic.

    snap.environment - (optional) object

    Default: {"TMPDIR": "$XDG_RUNTIME_DIR"}.

    Example: {"TMPDIR": "$XDG_RUNTIME_DIR"}.

    The custom environment. If you set this, it will be merged with the default.

    snap.grade - (optional) string

    Default: stable.

    Example: devel.

    The quality grade of the snap. It can be either devel (i.e. a development version of the snap, so not to be published to the “stable” or “candidate” channels) or stable (i.e. a stable release or release candidate, which can be released to all channels).

    snap.layout - (optional) object

    Default: undefined.

    Example: { "/var/lib/foo": { bind: "$SNAP_DATA/var/lib/foo" } }.

    Specifies any files to make accessible from locations such as /usr, /var, and /etc. See snap layouts to learn more.

    snap.plugs - (optional) array containing strings and or objects

    Default: ["desktop", "desktop-legacy", "home", "x11", "unity7", "browser-support", "network", "gsettings", "pulseaudio", "opengl"].

    Example: [ "default", { "browser-sandbox": { "interface": "browser-support", "allow-sandbox": true } }, "another-simple-plug-name" ].

    The list of plugs. If list contains default, it will be replaced with the default list, so, ["default", "foo"] can be used to add a custom plug foo in addition to the default list.

    Additional attributes can be specified using object instead of just name of plug:

    [
      {
        "browser-sandbox": {
          "interface": "browser-support",
          "allow-sandbox": true
        }
      },
      "another-simple-plug-name"
    ]

    snap.stagePackages - (optional) array of strings

    Default: ["libasound2", "libgconf2-4", "libnotify4", "libnspr4", "libnss3", "libpcre3", "libpulse0", "libxss1", "libxtst6"].

    Example: ["default", "depends"].

    The list of Ubuntu packages to use that are needed to support the app part creation. Like depends for deb. If list contains default, it will be replaced with the default list, so, ["default", "foo"] can be used to add custom package foo in addition to the defaults.

    snap.summary - (optional) string

    Default: The productName.

    Example: The super cat generator.

    A sentence summarising the snap. Max len. 78 characters, describing the snap in short and simple terms.

    snap.useTemplateApp - (optional) boolean

    Default: true if stagePackages is not specified.

    Example: false.

    Whether to use a template snap.

    uploadSizeLimit - (optional) number

    Default: 20. Example: 35.

    The max upload size (in MB). Before uploading your files to our servers, we check that the total file size is less than this number. If you are accidentally including unneccesary files in your app, check out the appPath and appFiles options.

    windows - (optional) object

    Default: We have good default settings for Windows.

    Example: { "icon": "./icon.ico" }.

    This object contains some options that only apply to the building & releasing for Windows.

    windows.icon - (optional) string

    Example: ./icon.ico.

    Default: The root icon is used.

    The path to your application's Windows desktop icon. It must be an ICO, ICNS, or PNG.

    Build lifecycle hooks (package.json scripts)

    Sometimes you want to do something before or during the build process. For example, you might want to run a script before the build starts, or you might want to run a script after the files have been packaged. Our lifecycle hooks provide a way to do this.

    To specify a script, add a scripts property to your package.json file. The key is the name of the script (prefixed by todesktop:), and the value is the path to the script.

    {
      "scripts": {
        "todesktop:beforeInstall": "./scripts/beforeInstall.js",
        "todesktop:afterPack": "./scripts/afterPack.js"
      }
    }

    When writing your script, you can follow this template:

    module.exports = async ({ pkgJsonPath, pkgJson, appDir, hookName }) => {
      /**
       * pkgJsonPath - string - path to the package.json file
       * pkgJson - object - the parsed package.json file
       * appDir - string - the path to the app directory
       * hookName - string - the name of the hook ("todesktop:beforeInstall" or "todesktop:afterPack")
       */
    };

    todesktop:beforeInstall - (optional) path to script

    Example: ./scripts/beforeInstall.js.

    The path to a script that will be run before the build starts.

    Example script:

    const { writeFile } = require("fs/promises");
    
    // Delete `internal` dependency from package.json
    module.exports = async ({ pkgJsonPath, pkgJson, appDir, hookName }) => {
      delete pkgJson.dependencies["internal"];
      await writeFile(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
    };

    todesktop:afterPack - (optional) path to script

    Example: ./scripts/afterPack.js.

    The path to a script that will be run after the app has been packed (but before it has been transformed into a distributable installer format and signed).

    The afterPack function also has the following arguments added to it's signature:

    • appPkgName - string - the name of the app package
    • appId - string - the app id
    • shouldCodeSign - boolean - whether the app will be code signed or not
    • outDir - string - the path to the output directory
    • appOutDir - string - the path to the app output directory
    • arch - string - the architecture of the app
    • packager - object - the packager object

    Example script:

    const { writeFile } = require("fs/promises");
    
    // Add a copyright file inside of the app directory on Mac only
    module.exports = async ({ appOutDir, packager }) => {
      if (os.platform() === "darwin") {
        const appName = packager.appInfo.productFilename;
        const appPath = path.join(`${appOutDir}`, `${APP_NAME}.app`);
        await writeFile(
          path.join(appPath, "copyright.txt"),
          `Copyright © ${new Date().getFullYear()} ${APP_NAME}`
        );
      }
    };

    App package.json requirements

    • Electron must be in your devDependencies and it must be a fixed version. I.e. it doesn't start with ^ or ~.
    • You must set the author property.

    Recommendations for app package.json

    • You should set the productName property. Otherwise, your app name will default to the value of the name property.

    FAQs

    One of my dependencies is a private package. How do I safely using it with ToDesktop CLI

    ToDesktop CLI is similar to Continuous Integration service so you can use the guide from here: https://docs.npmjs.com/using-private-packages-in-a-ci-cd-workflow/

    To summarize:

    1. Create a token using npm: npm token create --read-only.
    2. In ToDesktop's web UI go to Settings -> Build and Deploy.
    3. Enter an environment variable key of NPM_TOKEN and value should be the token entered above.
    4. Create an .npmrc file in the root of your project with the following contents:
    //registry.npmjs.org/:_authToken=${NPM_TOKEN}
    

    Note: Do not put a token in this file. You are specifying a literal value of ${NPM_TOKEN}. NPM will replace the value for you. 5. Add .npmrc to your appFiles array [".npmrc"] in todesktop.json.

    How do I create a staging version of my app?

    The easiest way to do this is to create a second app and switch the todesktop.json file to point to the staging app when you wish to deploy the staging app. There are a number of ways to do this. Let's do an example, save the file below as scripts/mod-staging.js.

    const path = require("path");
    const fs = require("fs");
    
    const rootDir = path.join(__dirname, "..");
    const packageJson = require(rootDir + "/package.json");
    const toDesktopJson = require(rootDir + "/todesktop.json");
    
    function modStaging() {
      packageJson.name = "myapp-staging";
      packageJson.productName = "My App Staging";
    
      toDesktopJson.id = "220718gzrs4pfe8";
      toDesktopJson.icon = "./resources/staging.png";
      toDesktopJson.appId = "myapp.staging.app";
    
      fs.writeFileSync(
        rootDir + "/package.json",
        JSON.stringify(packageJson, null, 2)
      );
      fs.writeFileSync(
        rootDir + "/todesktop.json",
        JSON.stringify(toDesktopJson, null, 2)
      );
    }
    
    modStaging();

    Create a similar script to revert the todesktop.json back to the original settings (let's save it as scripts/mod-revert.js). Then in your package.json, you could do something like this:

    {
      "name": "myapp",
      // ...
      "scripts": {
        "todesktop-build": "todesktop build",
        "todesktop-staging-build": "node scripts/mod-staging.js && todesktop build && node scripts/mod-revert.js"
      },
    }

    Now you can run npm run todesktop-build to build the production app. Or you can run npm run todesktop-staging-build to build the staging app.

    Changelog

    v1.2.1

    • Fix: When the build is finished the download link is now an Apple Silicon link if you are on an Apple Silicon Mac.

    v1.2.0

    • Add support for linux.noSandbox configuration option.
    • Fix Resolutions for Yarn 2+.

    1.1.2

    • Add support for asarUnpack configuration option.

    v1.1.0

    • Add support for beforeInstall and afterPack hooks.

    v1.0.0

    • Feature: Support multiple concurrent builds
    • Enhancement: Switched to presigned uploads (removes AWS dependency)
    • Fix: Fixed package resolution for Ink
    • Add PNPM support

    Keywords

    none

    Install

    npm i @todesktop/cli

    DownloadsWeekly Downloads

    2,661

    Version

    1.2.2

    License

    MIT

    Unpacked Size

    1.06 MB

    Total Files

    18

    Last publish

    Collaborators

    • sandeep1995
    • davej
    • isaacaderogba