
Security News
Axios Maintainer Confirms Social Engineering Attack Behind npm Compromise
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.
@todesktop/cli
Advanced tools
The ToDesktop CLI allows you to build and deploy your electron app with native installers, auto-updates and code signing included.
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.
Install the package with:
npm install -g @todesktop/cli
# or
yarn global add @todesktop/cli
You can use the ToDesktop CLI to work with an Electron application in 4 steps:
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:

Create a todesktop.json file in the root of your Electron project.
{
"$schema": "https://unpkg.com/@todesktop/cli@1.23.2/schemas/schema.json",
"schemaVersion": 1
"id": "your-todesktop-id",
"icon": "./desktop-icon.png",
"schemaVersion": 1
}
Alternatively, you can create a todesktop.js file. This allows you to use
JavaScript to dynamically generate your configuration. For example:
const path = require('path');
module.exports = {
id: process.env.TODESKTOP_APP_ID || 'your-default-todesktop-id',
icon: path.join(__dirname, 'assets', 'desktop-icon.png'),
schemaVersion: 1,
};
You can also create a todesktop.ts file for TypeScript projects with full type
checking and IntelliSense:
import type { Schema } from '@todesktop/cli';
import path from 'path';
const config: Schema = {
id: process.env.TODESKTOP_APP_ID || 'your-default-todesktop-id',
icon: path.join(__dirname, 'assets', 'desktop-icon.png'),
schemaVersion: 1,
nodeVersion: '18.12.1',
mac: {
category: 'public.app-category.productivity',
},
};
export default config;
See Project configuration for the full list of configuration options.
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);
To build your app, run the following command inside the root of your Electron project:
todesktop build
When prompted to login, use your email address and the accessToken from our dashboard. You can retrieve your access token by clicking on your name in the top right corner of the dashboard and selecting "Manage Access Token".
Once built, your app can then be downloaded and tested.
To release that build (i.e. publish new downloads and an auto-update), run:
todesktop release
To test whether that build works fine and can be successfully updated, run:
todesktop smoke-test
See the next section for more information on the available 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 build --config=<path.to.config.file>. Run a build with a different
configuration file (e.g., todesktop.staging.json or todesktop.prod.js).
todesktop build --async. Run a build in the background. This is handy for CI
environments.
todesktop build --webhook URL. Send a POST request to the webhook URL when
the build is finished. It's especially useful together with the --async
flag.
todesktop build --ignore-extends-errors. Ignore id and appId validation
errors when extending another configuration file (.json or .js).
todesktop build --introspect. Run a build with an active introspection
tunnel so you can inspect the build agent while it runs.
todesktop build --breakpoints=<comma-separated-list>. Requires
--introspect; accepts phase names (for example beforeInstall) and hook
forms such as hook:todesktop:beforeInstall:after. Aliases and wildcards like
hook:todesktop:beforeInstall:* are expanded automatically and the resolved
queue is printed before the build starts.
todesktop build --breakpoints=list. Print the catalog of supported
breakpoints with descriptions.
todesktop build --continue <buildId> --platform mac|windows|linux. Resume a
paused build from another terminal using the same account that initiated it.
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.
todesktop release <id> to release a specific build by ID.todesktop release --latest will release the latest build.--force to skip the interactive confirmation step.--config=<path.to.config.file> to use a different configuration
file.todesktop builds. View your recent builds.
todesktop builds <id> to view a specific build and its progress.todesktop builds --latest will show the latest build and it's progress.todesktop builds --count=<number> will show the last <number> builds.todesktop builds --format=json will output build data in JSON format.--config=<path.to.config.file> to use a different configuration
file.--exit to disable dynamic pagination and exit the process once the
build data has been displayed.todesktop logout. Logs you out.
todesktop smoke-test Check whether the build works and can be successfully
updated.
todesktop smoke-test <id> to test a specific build by ID.todesktop smoke-test --latest will test the latest build.--config=<path.to.config.file> to use a different configuration
file.todesktop introspect [buildId]. Connect to a running build’s shell when
introspection is enabled. If you omit the build ID, the CLI will prompt you to
pick a build and platform.
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.
The following options can be used with any command:
todesktop --config-dir <path>. Specify a custom directory for storing CLI
configuration and credentials. This overrides the default system config
directory. Can also be set via the TODESKTOP_CONFIG_DIR environment
variable.todesktop --ephemeral. Do not persist any configuration or credentials to
disk. All config is stored in memory only for the duration of the command.
This is useful for CI environments where credentials are provided via
environment variables and you don't want anything written to disk.Interactive introspection lets you open a shell on a live build agent and pause the build at deterministic breakpoints for deeper debugging.
todesktop build --introspect to start a build with an introspection
tunnel. The CLI prints availability notices and keeps the session attached
while the build runs.--breakpoints=list to print the supported pause points and their
descriptions.--breakpoints=beforeInstall,hook:todesktop:beforeInstall:after,afterPack
(requires --introspect). Phase names such as beforeInstall and hook forms
like hook:todesktop:beforeInstall:before are validated, deduplicated, and
expanded to cover aliases (for example hook:todesktop:beforeInstall:*
expands to both before/after hook breakpoints).mac paused at beforeInstall (lease expires in 20m).Enter to resume to the next breakpoint, x to skip the remaining
breakpoints, space to renew the lease (adds 10 minutes when less than 20
minutes remain), and Ctrl+C to detach without resuming.autoResumed in the CLI output and Firestore metadata.todesktop build --continue <buildId> --platform mac|windows|linux to
resume a paused platform. This mirrors pressing Enter in the interactive
prompt and requires that the target platform is currently paused.todesktop introspect [buildId] to connect to the build agent shell. If
you omit the build ID, the CLI presents a list of running builds with
introspection enabled followed by a platform picker that shows each platform’s
breakpoint and shell status (for example ⏸ mac (paused)).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
In CI environments, you may want to prevent the CLI from writing any credentials
or configuration to disk. Use the --ephemeral flag to store all config in
memory only:
todesktop build --ephemeral
You can also specify a custom config directory if needed (e.g., for isolated build environments):
todesktop build --config-dir /tmp/todesktop-config
# Or via environment variable
TODESKTOP_CONFIG_DIR=/tmp/todesktop-config todesktop build
If you need to run a build in the background, you can use the --async flag. To
get notified when the build is finished you can optionally specify a webhook URL
which will receive a POST request with the build data:
todesktop build --async --webhook https://example.com/build-finished-webhook
The webhook receives a POST request with the following JSON body:
// POST https://example.com/build-finished-webhook
{
appId: string;
accountUserEmail: string;
accountUserId: string;
artifacts: {
linux?: LinuxArtifactDownloads;
mac?: MacArtifactDownloads;
windows?: WindowsArtifactDownloads;
};
buildId: string;
endedAt: string; // 2023-01-01T00:00:00Z
errorMessage?: string;
requesterUserEmail: string;
requesterUserId: string; // The same as accountUserId or `contextUserId`
schemaVersion: number; // Currently always `1`
startedAt: string; // 2023-01-01T00:00:00Z
status: 'queued' | 'failed' | 'building' | 'preparation' | 'succeeded' | 'cancelled';
}
You can configure a webhook URL to receive notifications when a release is published. This is useful for triggering downstream processes like deployment pipelines or notifications.
You can read about how to do this in our release webhooks guide.
This describes all of the possible configuration options in your
todesktop.json, todesktop.js, or todesktop.ts file.
You can use:
todesktop.json) for static configurationtodesktop.js) that exports a configuration object for
dynamic configurationtodesktop.ts) that exports a configuration object with
full type checking and IntelliSenseUsing .js or .ts files allows for dynamic configuration, such as setting
values based on environment variables or computing paths.
Note:
.json files are available through the
JSON schema (described under Installation).ts) provide full type checking and IntelliSense when
using the exported Schema type from @todesktop/cliTo avoid confusion, the following terms will be used throughout this file:
todesktop.json,
todesktop.js, or todesktop.ts.$schema - (optional) stringExample: https://unpkg.com/@todesktop/cli@1.12.5/schemas/schema.json, ./node_modules/@todesktop/cli/schemas/schema.json
To enable JSON validation and IntelliSense for your todesktop.json file in compatible code editors, your editor needs to know where the schema file is located. You can add a $schema property to the top of your todesktop.json file, pointing to a version of the schema. This can be a local path or a hosted URL.
{
"$schema": "https://unpkg.com/@todesktop/cli@1.23.2/schemas/schema.json",
"id": "your-todesktop-id"
}
{
"$schema": "./node_modules/@todesktop/cli/schemas/schema.json",
"id": "your-todesktop-id"
}
appFiles - (optional) array of glob patternsDefault: ["**"]
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
distribution 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*) — matches everything except slashes (path separators).**) — matches zero or more directories.?) – matches any single character except slashes (path
separators).!) — 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) stringDefault: 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) stringDefault: .
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.:
electron command; i.e. npx electron {appPath}.package.json.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.
bundleWorkspacePackages - (optional) object{"enabled":false}Useful when your application is a monorepo (e.g. pnpm workspaces). You can configure whether the CLI bundles workspace packages alongside the app upload. When enabled, workspace dependencies referenced via workspace: or local file: specifiers are bundled with your application upload and dependency ranges are rewritten to file: paths so they install deterministically on the build servers.
{"enabled":true}bytenode - (optional) objectDefault: {"enabled":false}
Compile selected source files to .jsc using Bytenode during the build. Provide glob patterns relative to your appPath.
Experimental: This option may change or be removed in a future release.
bytenode.enabled - (optional) booleanDefault: false
Enable Bytenode compilation.
bytenode.files - (required when enabled) array of glob patternsGlob patterns relative to appPath for files to compile to Bytenode.
Example:
{
"bytenode": {
"enabled": true,
"files": ["dist/**/*.js", "main.js", "!renderer.js"]
}
}
fuses - (optional) objectConfigure Electron Fuses to enable or disable certain Electron features at package time. Fuses are compile-time feature flags that cannot be changed at runtime, providing security benefits. See https://www.electronjs.org/docs/latest/tutorial/fuses for more information.
Fuses allow you to harden your Electron application by disabling features that your app doesn't need. Once a fuse is flipped at build time, it cannot be changed at runtime.
Example:
{
"fuses": {
"runAsNode": false,
"enableNodeOptionsEnvironmentVariable": false,
"enableNodeCliInspectArguments": false,
"enableCookieEncryption": true,
"onlyLoadAppFromAsar": true
}
}
fuses.runAsNode - (optional) booleanControls whether the ELECTRON_RUN_AS_NODE environment variable is respected. When disabled, the env variable will be ignored. Default: true (enabled).
fuses.enableCookieEncryption - (optional) booleanControls whether the cookie store on disk is encrypted using OS-level cryptography. Default: false (disabled).
fuses.enableNodeOptionsEnvironmentVariable - (optional) booleanControls whether the NODE_OPTIONS environment variable is respected. When disabled, the env variable will be ignored. Default: true (enabled).
fuses.enableNodeCliInspectArguments - (optional) booleanControls whether command line arguments like --inspect are respected. When disabled, these arguments will be ignored. Default: true (enabled).
fuses.enableEmbeddedAsarIntegrityValidation - (optional) booleanControls whether Electron validates the integrity of the app.asar file. Requires the integrity block in the asar header. Default: false (disabled).
fuses.onlyLoadAppFromAsar - (optional) booleanControls whether Electron only loads the app from an asar archive. When enabled, Electron will not search for loose files. Default: false (disabled).
fuses.loadBrowserProcessSpecificV8Snapshot - (optional) booleanControls whether the browser process uses a V8 snapshot file located at browser_v8_context_snapshot.bin. Default: false (disabled).
fuses.grantFileProtocolExtraPrivileges - (optional) booleanControls whether pages loaded via file:// protocol get extra privileges. When disabled, file:// pages are more restricted. Requires Electron 29+. Default: true (enabled).
appProtocolScheme - (optional) string | string[]Default: no protocol scheme is registered
Example: word, ["word", "excel"]
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.
asar - (optional) booleanDefault: true
Whether to package your application's source code within an asar archive. You should only turn this off if you have a good reason to.
asarUnpack - (optional) boolean or array of glob patternsDefault: ["**/*.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.
buildVersion - (optional) stringDefault: auto-generated from build id
The build version. Maps to the CFBundleVersion on macOS, and FileVersion metadata property on Windows.
copyright - (optional) stringDefault: The package.json productName / name.
Example: Copyright © 1995 Walt Disney
The human-readable copyright line for the app.
dmg - (optional) objectOptions for customizing the macOS DMG (disk image) installer.
dmg.background - (optional) stringDefault: undefined (if undefined then we
use this template).
Example: ./mac-dmg-background.tiff
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) stringDefault: #ffffff
The background color (accepts css colors). Defaults to "#ffffff" (white) if no background image.
dmg.iconSize - (optional) numberDefault: 80
The size of all the icons inside the DMG. Defaults to 80.
dmg.iconTextSize - (optional) numberDefault: 12
The size of all the icon texts inside the DMG. Defaults to 12.
dmg.title - (optional) stringDefault: ${productName} ${version}
The title of the produced DMG, which will be shown when mounted (volume name). Macro ${productName}, ${version} and ${name} are supported.
dmg.contents - (optional) Array of objectsCustomize 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) objectThe 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
}
extends - (optional) stringDefault: null.
Example: ./todesktop.base.json or ./todesktop.base.js.
This is the path to a base configuration file (.json or .js). This is
especially useful for configuration sharing between different environments
(e.g., staging and production). The base configuration file can be a relative
path from the project root or an absolute path.
For more information about how to create a staging version of your app see: How do I create a staging version of my app?.
extraContentFiles - (optional) array of objectsDefault: []
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) stringDefault: 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) stringDefault: 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 objectsDefault: []
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 objectsAssociate a file type with your Electron app.
Example:
[
{
"ext": "ics",
"name": "Calendar"
}
]
ext String | String[] -
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.icon String - macOS and windows. Icon file name without extension. It points to ico file for Windows and icns for macOS. For example, if the icon value is "icons/py" then it will look for both "icons/py.ico" and "icons/py.icns" in your project directory.mimeType String -
linux-only. The mime-type.role = Default: 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.rank = Default: Default`` String -
macOS-only. Determines how Launch Services ranks this app among the apps that declare themselves editors or viewers of files of this type. The possible values are: Owner (this app is the primary creator of files of this type), Default (this app is an opener of files of this type; this value is also used if no rank is specified), Alternate (this app is a secondary viewer of files of this type), and None (this app is never selected to open files of this type, but it accepts drops of files of this type).filesForDistribution - (optional) array of glob patternsExample: ["!**/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 - stringExample: ./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 - stringExample: 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.

linux - (optional) objectExample: { "category": "Utility"}
This object contains some options that only apply to the building & releasing for Linux.
Default: We have good default settings for Linux.
linux.category - (optional) stringExample: Utility
The application category.
Default: undefined
linux.icon - (optional) stringExample: ./linux-icon.png
The path to your application's Linux desktop icon. It must be an ICNS or PNG.
Default: The root icon is used.
Note: to ensure the icon is never missing (e.g. this happens sometimes in
Ubuntu), set the
icon option
when creating your BrowserWindows.
linux.imageVersion - (optional) stringDefault: 0.0.12
Example: 0.1.0
The version of the Linux image that ToDesktop should use to build your app.
Linux Changelog:
0.1.0: Updated g++ → g++10, gcc → gcc10. WARNING: This compiler has been
updated to a newer version that is not compatible with older versions of Linux
like Ubuntu 20.04. You should probably only use this version if you know what
you're doing.0.0.11: Updated git 2.25.1 → 2.47.1 node 18.18.2 → 18.20.5linux.executableArgs - (optional) string[]Example: --enable-features=UseOzonePlatform,--ozone-platform=x11
Additional command-line arguments to pass to the executable in the Linux .desktop file Exec line.
This is useful if your Linux app requires specific flags to run reliably. For example, some apps need Ozone platform flags for Wayland/X11 compatibility:
{
"linux": {
"executableArgs": [
"--enable-features=UseOzonePlatform",
"--ozone-platform=x11"
]
}
}
Note: --no-sandbox is included by default. If you set executableArgs, it
will be preserved automatically unless you also set noSandbox to false.
linux.deb - (optional) objectConfiguration for Debian (.deb) packaging.
linux.deb.additionalDepends - (optional) string[]Additional package dependencies to append to ToDesktop's default .deb dependencies.
This appends to ToDesktop's default Debian dependency list:
libgtk-3-0libnotify4libnss3libxss1libxtst6xdg-utilslibatspi2.0-0libuuid1libsecret-1-0linux.deb.depends - (optional) string[]The list of package dependencies for the .deb package. This overwrites ToDesktop's default dependency list and linux.deb.additionalDepends.
linux.noSandbox - (optional) booleanDefault: 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.
includeSubNodeModules - (optional) booleanDefault: false
Whether to include all of the submodules node_modules directories
mac - (optional) objectDefault: 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 stringsDefault: []
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) stringDefault: 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) stringDefault: 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.entitlementsInherit - (optional) stringDefault: No entitlements file is provided by default.
Example: ./entitlementsInherit.mac.plist
The path to a child entitlements file for signing your application. It must be a plist file.
mac.extendInfo - (optional) objectDefault: {}
Example: { "NSUserNotificationAlertStyle": "alert" }
Extra entries for Info.plist.
mac.icon - (optional) stringExample: ./mac-icon.png
The path to your application's Mac desktop icon. It must be an ICNS, PNG, or Apple .icon package directory.
Note: Apple .icon paths should point to the Icon Composer package directory
(for example AppIcon.icon).
Note: Apple .icon support requires appBuilderLibVersion 26.8.1 or later.
Default: The root icon is used.
mac.requirements - (optional) stringDefault: No requirements file is used by default.
Example: ./requirements.txt
The path to the requirements file used when signing your application.
mas - (optional) objectExample: { "type": "development" }
This object contains options that only apply to building the application for Mac App Store.
Default: We use default development settings for Mac App Store.
mas.entitlements - (optional) stringDefault: No entitlements file is provided by default.
Example: ./entitlements.mas.plist
The path to an entitlements file for signing your application. It must be a plist file.
mas.entitlementsInherit - (optional) stringDefault: No entitlements file is provided by default.
Example: ./entitlementsInherit.mas.plist
The path to a child entitlements file for signing your application. It must be a plist file.
mas.provisioningProfile - (optional) stringDefault: No provisioning profile is used by default.
Example: ./mas.provisionprofile
The path to a provisioning profile for authorizing your application.
mas.type - (optional) stringDefault: development
Example: distribution
Whether to sign app for development or for distribution.
mas.minimumSystemVersion - (optional) stringExample: 12.0, 11.0, 10.15
The minimum macOS version required to run the app. Set to '12.0' or higher for arm64-only Mac App Store submissions.
mas.x64ArchFiles - (optional) stringDefault: not defined
Example: Contents/Resources/foobar/**
Minimatch pattern of paths that are allowed to be x64 binaries in both ASAR files.
nodeVersion - stringExample: 18.12.1
The version of Node.js that ToDesktop should use to build your app.
npmVersion - stringExample: 9.8.1
The version of NPM that ToDesktop should use for installation.
packageJson - (optional) objectDefault: {}
If you want to override the default package.json configuration, use the packageJson property. For example, you can use this to override the productName or version properties.
Example:
"packageJson": {
"extends": "package.json",
"name": "example-app-canary",
"productName": "Example App Canary",
"dependencies": {
"electron": "21.0.1"
}
}
You can also set the version of a dependency (or devDependency), such as
Electron Builder, to null. This will remove Electron Builder from the
effective package.json that ToDesktop will use.
"packageJson": {
"extends": "package.json",
"devDependencies": {
"electron-builder": null
}
}
packageManager - (optional) stringDefault: If bun.lockb or bun.lock exists, bun is used. If yarn.lock exists, yarn is used. If pnpm-lock.yaml or shrinkwrap.yaml exists, pnpm is used. Otherwise, npm is used.
Example: yarn
The package manager to use when installing dependencies. Valid values are npm, yarn, pnpm or bun.
pnpmVersion - stringExample: 8.10.5
The version of pnpm that ToDesktop should use for installation.
rebuildLibrary - (optional) stringDefault: app-builder
The library that ToDesktop should use for rebuilding native modules. Valid values are app-builder or @electron/rebuild.
schemaVersion - numberExample: 1
This is the todesktop.json schema version. This must be 1.
snap - (optional) objectExample: { "confinement": "classic", "grade": "devel" }
This object contains some options that only apply to the building for the Snap Store.
snap.after - (optional) array of stringsDefault: ["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 stringsDefault: 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 stringsDefault: 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) booleanDefault: false
Example: true
Whether or not the snap should automatically start on login.
snap.base - (optional) stringDefault: core18
Example: core20
The base snap to use for building this snap.
snap.buildPackages - (optional) array of stringsDefault: []
Example: ["libssl-dev", "libssh-dev", "libncursesw5-dev"]
The list of debian packages needs to be installed for building this snap.
snap.confinement - (optional) stringDefault: strict
Example: classic
The type of confinement supported by the snap. devmode, strict, or classic.
snap.environment - (optional) objectDefault: {"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) stringDefault: 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) objectDefault: 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 objectsDefault: ["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 stringsDefault: ["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) stringDefault: 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) booleanDefault: true if stagePackages is not specified.
Example: false
Whether to use a template snap.
updateUrlBase - (optional) stringDefault: ToDesktop's auto-update URL.
Example: https://example.com/updates
The URL to check for updates. You should only set this if you want to use your own self-hosted update server instead of ToDesktop's built-in update service. See https://www.github.com/ToDesktop/self-hosted for more information.
uploadSizeLimit - (optional) numberDefault: 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) objectExample: { "icon": "./icon.ico" }
This object contains some options that only apply to the building & releasing for Windows.
Default: We have good default settings for Windows.
windows.icon - (optional) stringExample: ./icon.ico
The path to your application's Windows desktop icon. It must be an ICO, ICNS, or PNG.
Default: The root icon is used.
windows.nsisCustomBinary - (optional) objectDefault: undefined
Allows you to provide your own makensis, such as one with support for debug logging via LogSet and LogText. (Logging also requires option debugLogging = true). It's not recommended to use it for production build.
Example:
{
"debugLogging": true,
"url": "https://download.todesktop.com/nsis/nsis-3.06.1-log.7z",
"checksum": "pB4LJ5s+bIjK6X+IrY4oyq1knpI1YNcykawJR1+ax9XqDULohiS6J7/Imin22rBBX6uoEDY2gvsaCcvqKkWAtA=="
}
Example of NSIS script which enables install logging:
!macro customInit
SetOutPath $INSTDIR
LogSet on
!macroend
windows.nsisInclude - (optional) stringDefault: undefined
Example: build/installer.nsh
The path to NSIS script to customize installer.
windows.publisherName - (optional) array of stringsDefault: Default to the common name from your code signing certificate.
Example: ["ABC Limited"]
The publisher name, exactly as in your code signing certificate. Several names can be provided. Defaults to common name from your code signing certificate. You should typically not include this property in your configuration unless you wish to transition to a new certificate in the future.
appBuilderLibVersion - (optional) stringExample: 22.14.13, latest
The version of app-builder-lib that ToDesktop should use for building your app. This can be a specific version, a semantic version range, or "latest". This can be useful if you need to use a specific version that includes certain features or fixes.
Note: Set this to 26.8.1 or later if you are using Apple Icon Composer assets
via mac.icon.
platformOverrides - (optional) objectDefault: {}
This option allows you to specify platform-specific configurations for Windows, macOS, and Linux builds. Most top-level configuration fields available in todesktop.json can be overridden within the windows, mac, or linux objects under platformOverrides.
Example:
{
"appId": "myapp.global.id",
"platformOverrides": {
"windows": {
"appId": "myapp.windows.id",
"copyright": "Copyright © My Company (Windows)"
},
"mac": {
"appId": "myapp.mac.id",
"mac": {
"category": "public.app-category.developer-tools"
}
},
"linux": {
"copyright": "Copyright © My Company (Linux)"
}
}
}
When a build is performed for a specific platform (e.g., Windows), the ToDesktop
CLI will first take the global configuration value for a field. If that same
field is defined within platformOverrides.windows, the platform-specific value
will be used instead.
In the example above:
appId will be myapp.windows.id.copyright will be Copyright © My Company (Windows).appId will be myapp.mac.id.mac.category will be public.app-category.developer-tools.appId will remain myapp.global.id (as it's not overridden for Linux).copyright will be Copyright © My Company (Linux).This is particularly useful for settings like appId, copyright, or
platform-specific configurations within the windows, mac, or linux blocks
(e.g., mac.category, windows.icon).
The fields that cannot be overridden using platformOverrides are:
id (the ToDesktop application ID)icon (the main application icon, though platform-specific icons like
windows.icon or mac.icon can be overridden)schemaVersionextendsplatformOverrides itselfSometimes 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:beforeBuild": "./scripts/beforeBuild.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:beforeBuild - (optional) path to scriptExample: ./scripts/beforeBuild.js.
The path to a script that will run before dependencies are rebuilt for target architectures.
Example script:
// Set environment variable depending on the architecture
module.exports = async ({
pkgJsonPath,
pkgJson,
appDir,
electronVersion,
platform,
arch,
hookName,
}) => {
if (arch === 'arm64') {
process.env.VARIABLE = 'value';
} else {
process.env.VARIABLE = 'alternative-value';
}
};
todesktop:beforeInstall - (optional) path to scriptExample: ./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 scriptExample: ./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:
ia32 = 0, x64 = 1,
armv7l = 2, arm64 = 3, universal = 4.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}`, `${appName}.app`);
await writeFile(
path.join(appPath, 'copyright.txt'),
`Copyright © ${new Date().getFullYear()} ${appName}`,
);
}
};
devDependencies and it must be a fixed version.
I.e. it doesn't start with ^ or ~.author property.productName property. Otherwise, your app name will
default to the value of the name property.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:
npm token create --read-only.NPM_TOKEN and value should be the
token entered above..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.
By default, ToDesktop uses version 1.x.x of Yarn if a yarn.lock file is
present in your project. You can override this by creating a .yarnrc.yml file
in your project directory and specifying the yarnPath property to point to
your specified version of yarn:
yarnPath: .yarn/releases/yarn-3.1.1.cjs
This can be done automatically by running yarn set version x.x.x from within
your project directory. This will create a .yarnrc.yml file and a
corresponding .yarn/releases/yarn-x.x.x.cjs that the yarnPath property
points to. This will also add a packageManager field in your package.json
with a value of yarn@x.x.x
It's important to ensure that the .yarn folder is included in your build. If
you had previously changed your todesktop.json's
appFiles property from its
default glob implementation of **, then please ensure that it includes the
.yarn directory:
Example: [".yarn/**", ".yarnrc.yml", "...include your other changes here..."]
You will want to exclude the .yarn directory in the distribution version of
your app. You can use the
filesForDistribution
property to achieve this:
Example: ["!.yarn/**", "!.yarnrc.yml"]
ToDesktop CLI supports the concept of a staging version of your app. This is useful if you want to test your app before releasing it to the public. To create a staging version of your app, you need to do the following:
Create a new app in ToDesktop's web UI.
Create a new configuration file, for example todesktop.staging.json or
todesktop.staging.js.
Add the following to your staging configuration file (e.g.,
todesktop.staging.json):
{
"extends": "./todesktop.json",
"id": "<ID_OF_YOUR_STAGING_APP>",
"appId": "myapp.staging.app",
"icon": "./resources/staging.png",
"packageJson": {
"name": "myapp-staging",
"productName": "My App (Staging)"
}
}
{
"name": "myapp",
// ...
"scripts": {
"todesktop-build": "todesktop build",
"todesktop-staging-build": "todesktop build --config=./todesktop.staging.json",
},
}
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.
No problem, this can be achieved with a
postInstall script in
combination with ToDesktop's TODESKTOP_CI and
TODESKTOP_INITIAL_INSTALL_PHASE environment variables.
| Name | Description |
|---|---|
TODESKTOP_CI | Set to true when running on ToDesktop build servers |
TODESKTOP_INITIAL_INSTALL_PHASE | Set to true when running the first npm/yarn/pnpm install on ToDesktop build servers |
First, let's create a file called todesktop-postinstall.js or something
similar in the root of your app (alongside pkckage.json). This file is going
to run a script to compile typescript after your dependencies have been
installed. It could look something like this
const { exec } = require('child_process');
const { promisify } = require('util');
const execAsync = promisify(exec);
async function postInstall() {
const firstInstallOnToDesktopServers =
process.env.TODESKTOP_CI && process.env.TODESKTOP_INITIAL_INSTALL_PHASE;
if (firstInstallOnToDesktopServers) {
console.log('➔ Building typescript on ToDesktop servers');
await execAsync('npm run build', {
stdio: 'inherit',
});
} else {
console.log('➔ Not on ToDesktop servers... Do nothing.');
}
}
postInstall();
Next, add the following to your package.json:
{
// ...
"scripts": {
// This is our existing typescript build script
"build": "tsc -p .",
// Our new postinstall script will run the script above when on ToDesktop servers
"postinstall": "node todesktop-postinstall.js"
}
}
Now, when we build your app on ToDesktop servers, it will also run your custom
build script after all dependencies have been installed.
appPath still reject invalid
Electron version ranges.appBuilderLibVersion: "latest" in todesktop.json during builds..icon package support via mac.icontodesktop.json.linux.deb.depends in todesktop.jsonlinux.executableArgs configuration option for passing
additional command-line arguments to the Linux executable.whoami command not working when authenticated via environment
variables (TODESKTOP_EMAIL and TODESKTOP_ACCESS_TOKEN)whoami commandcatalog: dependencies (without workspace:*
dependencies) can build correctly with Bun and other package managers.todesktop build --introspect flag and
todesktop introspect [buildId] command for interactive shell access to
in-progress builds--config-dir and --ephemeral global flags for custom config
storagemas.minimumSystemVersion config optionwindows.icon now accepts .ico files without triggering schema
validation errors.bundleWorkspacePackages in config to specify whether the CLI
bundles workspace packages alongside the app upload.todesktop.ts configuration file with full TypeScript type
checking and IntelliSense.Schema type from @todesktop/cli for TypeScript configuration files.todesktop.js configuration file for dynamic configurations.platformOverrides in config to specify platform-specific
overrides for app configuration$schema in config to enable JSON schema validation and IDE
intellisenseBuildCommand that caused errors.catalog: protocol (used by PNPM) for electron dependency version in
package.json.appFiles to not error when no *.js files are found (but *.ts
files are present)main.logupdateUrlBase in config to specify a custom
auto-update URLbeforeBuild hook.linux.imageVersion now supports any string, not just semver.appId is not defined in an extended
todesktop.json.linux.imageVersion to explicitly set the version of the
Linux image that ToDesktop should use to build your app.id and appId validation when extending another
todesktop.json file. Can be disabled with the --ignore-extends-errors
flag.snap.base in snap configurationtodesktop.json VSCode/Cursor
validationtodesktop.json propertiestodesktop.jsonwindows.publisherNamemas.x64ArchFiles in config.mac.entitlementsInherit in config.mas.entitlements in config.mas.entitlementsInherit in config.mas.provisioningProfile in config. Removed
mac.provisioningProfile as a result.mas.type in config.mac.provisioningProfile in config.buildVersion in config.includeSubNodeModules in config.@electron/rebuild as a custom rebuildLibrary in your
configuration file.yarnVersion in config. Instead use .yarnrc.yml file to
specify yarn version.--webhook flag for todesktop build command--async flag to run a build in the in the backgroundyarnVersion in the configuration filepnpmVersion in the configuration filenpmVersion in the configuration filemac.requirements)appBuilderLibVersion in the configuration
filetodesktop smoke-test commandwindows.nsisCustomBinary in the
configuration filenodeVersion in the configuration filewindows.nsisInclude in the configuration file--exit flag for todesktop builds.todesktop builds --format=json.todesktop builds --count=<number>.packageJson override.packageJson to null.release and builds commands.extends and packageJson fields to the configuration file.--config option to pass a different configuration file.linux.noSandbox configuration option.asarUnpack configuration option.beforeInstall and afterPack hooks.FAQs
The ToDesktop CLI allows you to build and deploy your electron app with native installers, auto-updates and code signing included.
The npm package @todesktop/cli receives a total of 10,766 weekly downloads. As such, @todesktop/cli popularity was classified as popular.
We found that @todesktop/cli demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.