Seed Project

Overview

Available since io.Connect Desktop 10.0

The io.Connect seed project is the main approach for delivering, customizing, and packaging io.Connect Desktop. The seed project enables you to control the entire process of creating your own custom distribution package, reducing the time for adopting new platform versions.

The seed project provides the following benefits:

  • installing the latest or a specific version of the platform components;
  • integrating the platform license key;
  • customizing the platform system configuration;
  • customizing the platform assets like logos, icons, splash screen, loader, and more;
  • customizing various branding features via the CLI configuration (the product name and description, the names and icons of the produced artifacts);
  • development and production modes that support different configuration settings;
  • templates for the customizable system apps (e.g., Workspaces App, Web Group App, Launchpad);
  • adding your own custom apps to be packaged with your platform build;
  • test templates for writing and executing your own tests;
  • producing artifacts (installers, bundles) for Windows and macOS;
  • code signing settings;
  • publishing and auto update settings;
  • CI/CD integration settings;

The @interopio/iocd-cli library provides an io.Connect CLI which is a necessary tool for creating and managing a seed project.

⚠️ Note that you can use npx to execute the CLI commands without installing the @interopio/iocd-cli library globally. Some of the CLI commands are available as script definitions in the package.json file of the @interopio/iocd-cli library and can be executed via npm.

ℹ️ For more details on the available io.Connect CLI commands, see the CLI section.

Requirements

To be able to create and use an io.Connect seed project, the following requirements must be met:

  • Node.js v22 or later;
  • npm v9 or later;
  • OS: Windows 10 or later, macOS 11 or later;
  • License: the seed project requires a valid license key for io.Connect Desktop;

Quick Start

Execute the following steps to quickly setup your seed project.

  1. Create the seed project:

Use npx to execute the create package command directly:

npx @interopio/iocd-cli@latest create
  1. Follow the prompts and provide a product name, select the desired platform components, select which templates to add for customization, and provide a valid license key.

  2. Install the necessary dependencies for the seed project:

npm install
  1. Prepare the project for usage by executing the following command. This will install the selected components and the dependencies for all customizable apps:
npm run setup
  1. To run your seed project in development mode in order to test your platform and your interop-enabled apps, execute the following command:
npm run dev
  1. After customizing and testing your platform project, you can produce build artifacts both for Windows and for macOS by executing the following command:
npm run build
  1. Use the build artifacts to distribute and deploy your platform project.

⚠️ Note that the io.Connect Desktop installation folder can be placed at any location. The io.Connect platform runs independently of its location in the file system. However, you should consider the path length limitations on Windows which allow for a maximum of a 256-character path string. The longest path in the io.Connect Desktop installation is 91 characters. You should consider this when deciding on a location for the installation bundle when using a bundle deployment, or if you decide to move the default installation folder to a new location when using an installer.

Project Structure

The following demonstrates the basic structure of the seed project:

.
├── apps/                       # Contains the customizable system apps. You can place your own apps here to be bundled with the package.
├── components/                 # Downloaded platform components.
│   ├── iocd/                   # The main platform component (required).
│   └── <other-components>      # Additional licensed components (devTools, demos, and more).
├── config/                     # Seed project configuration files.
│   ├── forge.config.js         # Electron Forge configuration.
│   ├── iocd.cli.config.json    # io.Connect CLI configuration.
│   └── iocd.license.key        # License key file.
├── modifications/              # Contains all platform customizations (icons, images, and more) and configuration overrides.
│   ├── base/                   # Modification that will be applied in all modes (development/build).
│   ├── dev/                    # Modifications that will be applied only in development mode.
│   └── build/                  # Modifications that will be applied only during production builds.
├── tests/                      # Automated tests.
│   └── basic.test.js           # Example test suite.
├── .github/workflows/          # Pre-configured GitHub Actions workflow example for CI/CD automation.
├── package.json
└── README.md

Components

The following table lists the currently available components that can be installed via the seed project:

Component Description Platforms
"iocd" Required. The main io.Connect Desktop application runtime. Windows, macOS
"bbg" Bloomberg Terminal V3 integration adapter. Windows, macOS
"bbg-mdf" Bloomberg Market Data Feed integration adapter. Windows
"excel" Microsoft Excel integration adapter for io.Connect Desktop. Windows
"outlook" Microsoft Outlook integration adapter for io.Connect Desktop. Windows
"word" Microsoft Word integration adapter for io.Connect Desktop. Windows
"fidessa" Fidessa integration adapter for io.Connect Desktop. Windows
"demos" A set of web-based demo applications showcasing various features of io.Connect Desktop. Windows, macOS
"devTools" Developer tools for io.Connect Desktop. Windows, macOS

Configuration

Basic Settings

The metadata for your product can be configured in the package.json file:

{
    "name": "my-product-slug",
    "version": "1.0.0",
    "description": "My product description.",
    "productName": "My Product Name",
    "author": "My Company"
}

The values specified in these fields are automatically populated by the io.Connect CLI when you execute the create command.

The following table describes the purpose of each property:

Property Type Description
"author" string Used as a company name (also used to auto-generate copyright).
"description" string Used as a product description in installers and metadata.
"name" string Used as a project identifier (e.g., folder name, executable name, package name, and more).
"productName" string Used as a human-readable product name displayed to users in UIs.
"version" string Used as a version for your platform app.

The settings for configuring the io.Connect CLI are in the iocd.cli.config.json file located in the /config folder.

The following is a basic configuration for the io.Connect CLI specifying the store from which to download the platform components and the list of components and component versions to retrieve:

{
    "components": {
        "store": {
            "github": {
                "repo": "interopio/iocd-components/releases"
            }
        },
        "list": {
            "iocd": "latest"
        }
    }
}

ℹ️ For details on all available configuration settings for the io.Connect CLI, see the complete JSON schema for the iocd.cli.config.json file. The schema is located in the /node_modules/@interopio/iocd-cli/dist/schemas folder. Add a $schema property to your configuration file to enable IDE autocompletion and validation.

License Key

io.Connect Desktop requires a valid license key to operate.

ℹ️ For details on how to obtain a license key for io.Connect Desktop 10.0, contact us.

During the process of creating the seed project, you will be prompted to provide a valid license key for io.Connect Desktop. Copy and paste your license key when prompted to continue the project creation. If you don't provide a valid license key, you won't be able to create a seed project.

The io.Connect CLI will create automatically an iocd.license.key file located in the /config folder of the seed project. You can use this file to manage your license key later.

⚠️ Note that you must never commit the iocd.license.key file in your project repository to prevent leaking your license key. By default, this file is ignored in the .gitignore settings.

For the purpose of setting up CI/CD automation, you can also use the IOCD_LICENSE_KEY environment variable to store and obtain the license key from your GitHub secrets during build.

Customization

Modifications

Modifications are the recommended way to customize io.Connect Desktop components without directly editing component files. They allow you to change configurations, add apps, modify assets, and override default behavior while preserving your changes across component updates.

Key Concepts:

  • Modifications are stored separately from components in the modifications/ folder
  • Changes persist when components are updated or reinstalled
  • Mode-specific modifications allow different behavior in dev vs. build mode
  • Files are copied or merged into components when running npm run dev or npm run build

Directory Structure:

modifications/
├── base/                     # Applied in all modes.
│   └── iocd/
│       ├── config/
│       │   └── apps/
│       └── assets/
├── dev/                      # Applied only in dev mode
│   └── iocd/
│       └── config/
└── build/                    # Applied only in build mode.
    └── iocd/
        └── config/

Processing Order:

  1. Base modifications (modifications/base/) are applied first
  2. Mode-specific modifications (modifications/dev/ or modifications/build/) are applied second, overriding base when needed

Common Use Cases:

  • Replace logos and icons in modifications/base/iocd/assets/
  • Configure system settings in modifications/base/iocd/config/
  • Add app definitions in modifications/base/iocd/apps/
  • Use different URLs for dev (localhost) vs. build (file://) in mode-specific folders

Special File Types:

  • .json.merge - Deep merges with existing JSON instead of replacing
  • .delete - Removes the corresponding file
  • .replace marker - Replaces entire directory (place in directory to replace)

Deep Merging with .json.merge Files

The .json.merge extension enables you to selectively modify JSON configuration files without replacing them entirely. This is particularly useful when you want to override specific settings while preserving all other default values.

How It Works

When a file is named with the .json.merge extension (e.g., system.json.merge), it is deep-merged with the corresponding target file (system.json). The merge process:

  1. Recursively traverses nested objects
  2. Adds new properties from the merge file
  3. Overrides existing properties with values from the merge file
  4. Preserves properties not mentioned in the merge file

Example: Object Deep Merge

If the target system.json contains:

{
    "logging": {
        "level": "info",
        "appender": "default",
        "maxFiles": 10
    },
    "features": {
        "autoSave": true,
        "notifications": true
    }
}

And your merge file system.json.merge contains:

{
    "logging": {
        "level": "debug"
    },
    "features": {
        "devTools": true
    }
}

The result will be:

{
    "logging": {
        "level": "debug",
        "appender": "default",
        "maxFiles": 10
    },
    "features": {
        "autoSave": true,
        "notifications": true,
        "devTools": true
    }
}

Notice that:

  • logging.level is overridden to "debug"
  • logging.appender and logging.maxFiles are preserved
  • features.devTools is added
  • features.autoSave and features.notifications are preserved

Platform-Specific Merge Files

You can create platform-specific merge files by adding a platform suffix:

  • system.json.merge-darwin - Applied only on macOS
  • system.json.merge-win32 - Applied only on Windows

Multiple merge files can target the same configuration file and will be applied in order.

Array Merging in .json.merge Files

ℹ️ Array merging with directive support is available since @interopio/iocd-cli version 0.0.71.

When using .json.merge files, arrays are concatenated by default with the existing arrays in the target file. This allows you to add new items to existing arrays without losing the original content.

You can control array merge behavior using special directive objects:

Directive Behavior Description
(default) Concatenate Arrays are merged by appending new items to existing ones
$replace Replace entirely The array is completely replaced with the new values
$prepend Add to beginning New items are added at the start of the existing array
$append Add to end Explicitly adds items to the end (same as default)
$remove Remove items Matching items are removed from the existing array

Example: Default Array Concatenation

If the target apps.json contains:

{
    "apps": ["app1", "app2"]
}

And your merge file apps.json.merge contains:

{
    "apps": ["app3", "app4"]
}

The result will be:

{
    "apps": ["app1", "app2", "app3", "app4"]
}

Example: Replacing an Array

To completely replace an array instead of concatenating, use the $replace directive:

{
    "apps": { "$replace": ["only-this-app"] }
}

This is useful when you want to override a list entirely rather than extend it.

Example: Prepending to an Array

To add items at the beginning of an existing array, use the $prepend directive:

{
    "startupScripts": { "$prepend": ["init.js", "setup.js"] }
}

This ensures your items appear before any existing items in the array.

Example: Removing Items from an Array

To remove specific items from an existing array, use the $remove directive:

{
    "disabledPlugins": { "$remove": ["legacy-plugin", "deprecated-feature"] }
}

For objects within arrays, the removal uses deep comparison:

{
    "apps": { "$remove": [{ "name": "unwanted-app" }] }
}

Combining Object and Array Merging

You can combine object deep merging with array directives in the same merge file:

{
    "logging": {
        "level": "debug"
    },
    "features": {
        "enabledPlugins": ["my-plugin"],
        "disabledPlugins": { "$remove": ["old-plugin"] }
    },
    "startupApps": { "$prepend": ["dashboard"] }
}

This example:

  • Overrides logging.level to "debug"
  • Concatenates "my-plugin" to features.enabledPlugins
  • Removes "old-plugin" from features.disabledPlugins
  • Prepends "dashboard" to the startupApps array

System Configuration

The io.Connect Desktop system configuration (the system.json file) controls platform-wide settings like auto-updates, logging, and feature flags. To customize these settings, create modification files that merge with the default configuration.

Location:

modifications/base/iocd/config/system.json.merge

The following example demonstrates how to enable auto updates:

{
    "autoUpdater": {
        "enabled": true,
        "updateSource": {
            "type": "Service",
            "baseUrl": "https://updates.yourcompany.com"
        },
        "updateIntervalMinutes": 60
    }
}

The following example demonstrates how to configure the system logging:

{
    "logging": {
        "level": "info",
        "appender": "default"
    }
}

Mode-Specific Configurations

Using different settings for development and production build mode:

Dev mode (modifications/dev/iocd/config/system.json.merge):

{
    "logging": {
        "level": "debug"
    },
    "features": {
        "devTools": true
    }
}

Build mode (modifications/build/iocd/config/system.json.merge):

{
    "logging": {
        "level": "error"
    },
    "features": {
        "telemetry": true
    }
}

When modifying the system configuration, consider the following:

  • Use .merge extension to deep merge with existing configuration.
  • Without .merge, the file completely replaces the original.
  • Changes are applied when running npm run dev or npm run build.
  • Environment variables like ${PRODUCT_VERSION} are automatically expanded.

Icons & Images

Default logo:

Replace the default logo files in modifications/base/iocd/assets/images/:

modifications/base/iocd/assets/
└── images/
    ├── logo.ico   # Windows executable icon (multiple resolutions)
    ├── logo.icns  # macOS app bundle icon (multiple resolutions)
    └── logo.png   # App icon (used in UI)

Requirements:

  • logo.ico: Windows icon file with multiple sizes (16x16, 32x32, 48x48, 256x256)
  • logo.icns: macOS icon file with multiple sizes (use Icon Composer or iconutil)
  • logo.png: PNG file, recommended size 512x512

Apps

io.Connect Desktop includes several built-in apps that you can replace with your own custom versions:

  • Workspaces - Workspace management UI
  • Groups - Window grouping UI
  • Splash Screen - Platform splash screen
  • Launchpad - App launcher
  • Notifications - Notification center

Apps in the apps/ folder allow you to customize these built-in apps or add entirely new functionality. This approach keeps your core platform apps in the same repository, eliminating the need to manage them across multiple repositories and simplifying version control, deployment, and coordination.

Using Template Apps

Template apps can be selected during project creation or added later:

# Add a template app
npx @interopio/iocd-cli@latest apps add workspaces

# List available templates
npx @interopio/iocd-cli@latest apps list --available

Available templates:

  • workspaces - Workspace management
  • groups - Window grouping
  • splash-screen - Loading screen
  • launchpad - App launcher

Once added, build your implementation on top of the template in the apps/ folder.

Creating Custom Apps

For custom apps, create a folder in apps/ with an iocd.app.json file:

apps/
└── my-custom-app/
    ├── iocd.app.json       # Defines modifications and build behavior
    ├── package.json
    └── src/

Example iocd.app.json:

In this example:

  • Dev mode (triggered by npm run dev): Executes a start script (typically starts a dev server with hot-reload) and copies the development app configuration so the app definition points to the dev server
  • Build mode (triggered by npm run build): Executes a build script (typically builds optimized production assets) and copies the final built assets to the modifications folder
{
   "dev": {
        "script": "start",
        "modifications": [
            {
                "source": "/config/my-app-dev.json",
                "destination": "/modifications/dev/iocd/config/apps/my-app.json"
            }
        ]
    },
    "build": {
        "script": "build",
        "modifications": [
            {
                "source": "/dist/",
                "destination": "/modifications/build/iocd/assets/my-app"
            }
        ]
    }
}

The iocd.app.json file defines:

  • base: Array of modifications applied in all modes
  • dev: Object with optional script (npm script name) and modifications array
  • build: Object with optional script (npm script name) and modifications array

Managing Apps

# Install app dependencies
npx @interopio/iocd-cli@latest apps install

# Start apps in dev mode
npm run apps-dev

# Build apps for production
npx @interopio/iocd-cli@latest apps build

Development

Development mode allows you to quickly start io.Connect Desktop with all your configured changes and apps, enabling rapid iteration and testing during development.

When you run dev mode, the CLI will:

  1. Apply all relevant modifications - Base modifications and dev-specific modifications are copied to components
  2. Launch the platform - Starts the platform with all changes applied
npm run dev

⚠️ Note that in order to run any custom apps you may have in the /apps folder, you must run npm run apps-dev in a separate terminal to start them. If you don't start them, io.Connect Desktop may fail to start.

Installing & Updating Components

To install a component or update an existing component while in development mode, use the following command:

npx @interopio/iocd-cli@latest components install <component-name>

This command will download and install the latest version of the specified component.

If you want to install a specific version, use:

npx @interopio/iocd-cli@latest components install <component-name>@<version>

Using Pre-Releases

You can also use pre-release versions of the platform components via the io.Connect CLI. The list of all published releases is available at https://releases.interop.io/components.html.

To enable using a pre-release version, set the "usePrereleases" property to true in the "components.store.github" object in the config/iocd.cli.config.json file:

{
    "components": {
        "store": {
            "github": {
                "repo": "interopio/iocd-components/releases",
                "usePrereleases": true
            }
        }
    }
}

After enabling the flag, install the desired pre-release version by specifying the exact version:

npx @interopio/iocd-cli@latest components install iocd@10.1.0

⚠️ Note that pre-release versions are intended for testing and evaluation purposes. They may contain experimental features or changes that aren't yet fully stable. It's recommended to use stable releases for production environments.

Testing

Testing is based on WebdriverIO and depends on the @interopio/wdio-iocd-service package, which enables starting and controlling io.Connect Desktop from WebdriverIO. This allows you to create and run comprehensive end-to-end (E2E) tests for your io.Connect Desktop platform.

Running Tests

Tests are written in the tests/ folder and can be executed using:

# Run all tests
npm test

# Or using the WebdriverIO CLI directly
npx wdio run ./wdio.config.ts

Writing Tests

Tests are written using WebdriverIO syntax with the io.Connect Desktop service handling app lifecycle. Example test structure:

describe("io.Connect Desktop Platform", () => {
    it("should launch successfully", async () => {
        // Your test logic here.
        // The @interopio/wdio-iocd-service handles starting/stopping io.Connect Desktop.
    });
});

Add your test files to the tests/ directory. They'll run automatically in CI/CD pipelines.

Building for Production

The build process creates production-ready installers for distribution. It orchestrates multiple steps to produce signed, optimized packages ready for deployment.

What happens during build:

  1. Build all apps - Executes build scripts for each app in production mode
  2. Reinstall components - Downloads and installs fresh component versions
  3. Apply all modifications - Copies base and build-specific modifications to components
  4. Code sign binaries - Signs executables and libraries (if configured)
  5. Create build artifacts - Generates installers (.exe setup on Windows, .dmg on macOS, .zip archives)
  6. Publish to release server - Uploads artifacts for auto-updates (if configured)

Build System:

The build process is based on Electron Forge, a complete toolchain for building and packaging Electron apps. The main configuration is located in /config/forge.config.js, where you can customize makers, publishers, and build behavior.

Build Commands

# Build installer
npm run build

# Build options
npm run build --output custom/path         # Custom output directory
npm run build --publish-only               # Skip build, only publish
npm run build-skip-install                 # Skip component installation

Build Output

Depending on the OS, you can configure Electron Forge makers to produce different types of artifacts. The following configurations have been tested:

Windows

  1. Squirrel.Windows installer (.exe setup)
  • You can change the install GIF by replacing the install.gif in assets folder.

  • If using a Windows installer, you can hide the installer UI during the installation process by using the --silent command line argument:

io-connect-desktop-setup.exe --silent
  • The app will be installed into %LocalAppData%\YourAppName. Squirrel is opinionated and does not allow changing this path.

  • By default the UserData folder generated by the platform will stay in %LocalAppData%\interop.io\io.Connect Desktop folder. You can change this by add the following system.json.merge-win32 file in modifications/base/iocd/config/system.json.merge-win32 (the merge file has win32 suffix which indicates it is only applied on Windows OS):

{
    "paths": {
        "userData": "%LocalAppData%/${PRODUCT_SLUG}/UserData/%IO_CD_ENV%-%IO_CD_REGION%",
        "cache": {
            "location": "%LocalAppData%/${PRODUCT_SLUG}/Cache/%IO_CD_ENV%-%IO_CD_REGION%",
            "copy": true
        }
    }
}
  1. Portable ZIP archive

macOS

  1. DMG disk image

  2. ZIP archive

The full list of makers is available in the Electron Forge documentation.

Code Signing

Code signing ensures that your app is trusted by operating systems and users can verify that it hasn't been compromised. Both Windows and macOS require code signing for distribution.

The settings for code signing are located under the "codeSign" property of the "win" top-level key for Windows and the "mac" top-level key for macOS in the iocd.cli.config.json seed project configuration file.

Windows

The "type" property of the "codeSign" object under the "win" top-level key accepts the following values:

Value Description
"custom" Use a custom signing script.
"signtool" Use a certificate and a sign tool to sign. The certificate can be retrieved from a PFX certificate file or from the Windows Certificate Store.
"off" Disable code signing.
  • PFX Certificate File

The is the most common method for code-signing on Windows. It uses a PFX certificate with a password. The PFX file contains both the certificate and the private key needed by the sign tool.

To configure signing via a PFX certificate file, provide the path to the file and the PFX password:

// In `config/iocd.cli.config.json`.
{
    "win": {
        "codeSign": {
            "type": "signtool",
            "pfxPath": "path/to/certificate.pfx",
            "pfxPassword": "${WIN_PFX_PASS}"
        }
    }
}
  • Certificate from the Windows Certificate Store

This method uses a certificate that already exists in the Windows Certificate Store. This is the approach you would use with services like DigiCert KeyLocker. For instance, with KeyLocker, you sync the certificate into the local Windows Certificate Store and sign using the certificate hash. The advantage is that the private key never leaves the HSM which is good for more security-sensitive environments.

To configure signing via a certificate from the Windows Certificate Store, provide the certificate SHA-1:

// In `config/iocd.cli.config.json`.
{
    "win": {
        "codeSign": {
            "type": "signtool",
            "certificateSha1": "${WIN_CERT_SHA1}"
        }
    }
}

When configuring your code signing settings, consider the following:

⚠️ Note that if using DigiCert KeyLocker, you must run smctl windows certsync before building to sync certificates to the Windows Certificate Store.

  • Custom Script

For advanced signing scenarios, you can provide a custom signing script:

// In `config/iocd.cli.config.json`.
{
    "win": {
        "codeSign": {
            "type": "custom",
            "customCodeSignScriptPath": "path/to/custom-sign.js"
        }
    }
}

Your custom script should export a function that receives the binary path and config:

// custom-sign.js
module.exports = async function(binaryPath, config) {
    // Your custom signing logic here.
    console.log(`Signing ${binaryPath}`);
    // Use any signing tool or API you need.
};
  • Excluding Folders from Signing

Available since @interopio/iocd-cli 0.0.74.

You can exclude specific folders from code signing on Windows by using the "excludeFolders" property of the "codeSign" object. This is useful when certain folders contain third-party binaries that are already signed or don't need to be signed with your certificate.

The "excludeFolders" property accepts an array of glob patterns. Paths are matched relative to the io.Connect Desktop component directory using forward slashes. By default, no folders are excluded — all binaries found in the build output are signed.

Supported glob syntax:

Pattern Description
** Matches any number of path segments (including zero).
* Matches anything within a single path segment.
? Matches a single character.
! (prefix) Negates a pattern (re-includes previously excluded paths).

Patterns are evaluated in order and the last matching pattern wins (similar to .gitignore).

Example configuration that excludes all binaries under components/ and assets/gw-legacy/, but re-includes components/my-addon/:

// In `config/iocd.cli.config.json`.
{
    "win": {
        "codeSign": {
            "type": "signtool",
            "pfxPath": "path/to/certificate.pfx",
            "pfxPassword": "${WIN_PFX_PASS}",
            "excludeFolders": [
                "components/**",
                "assets/gw-legacy/**",
                "!components/my-addon/**"
            ]
        }
    }
}

macOS

On macOS the process is a little different and more tightly controlled. It also requires an extra step called notarization.

Code Signing Configuration

The "type" property of the "codeSign" object under the "mac" top-level key accepts the following values:

Value Description
"certificate" Use a .p12 certificate file.
"custom" Use a custom signing script.
"keycahin" Use a certificate from macOS Keychain.
"off" Disable code signing.
  • Keychain

This methods uses a certificate from macOS Keychain. This is the mode to use if you want to use an Apple Developer ID certificate. You must download the certificate from the Apple Developer Portal, import it into your Keychain, and it will become available for code signing tools.

// In `config/iocd.cli.config.json`.
{
    "mac": {
        "codeSign": {
            "type": "keychain",
            "identity": "Developer ID Application: Your Company (TEAM_ID)"
        }
    }
}

You can use the following properties of the "codeSign" object to specify your Developer ID Application identity and Keychain to use:

Property Type Description
"identity" string Developer ID Application identity or SHA-1 hash (optional, auto-selected if not specified).
"keychain" string Keychain name or path (optional, uses the default Keychain if not specified).
  • Certificate

This method uses a .p12 certificate file that's imported into a temporary keychain during the build. The temporary keychain is removed after the build.

// In `config/iocd.cli.config.json`.
{
    "mac": {
        "codeSign": {
            "type": "certificate",
            "certificatePath": "./certs/mac-cert.p12",
            "certificatePassword": "${MAC_CERT_PASSWORD}"
        }
    }
}
  • Custom Script

For advanced signing scenarios, you can provide a custom signing script:

// In `config/iocd.cli.config.json`.
{
    "mac": {
        "codeSign": {
            "type": "custom",
            "customCodeSignScriptPath": "path/to/custom-sign.js"
        }
    }
}

Your custom script should export a function that receives the app bundle path and config:

// custom-sign.js
module.exports = async function(appBundlePath, config) {
  // Your custom signing logic here
  console.log(`Signing ${appBundlePath}`);
  // Use any signing tool or API you need
};

Notarization Configuration

Notarization is required for distributing any macOS app outside the App Store. This is how Apple verifies that the app is safe and hasn't been compromised. If an app isn't notarized, users will see warnings or may not be able to run it at all.

The notarization settings are located under the "notarization" property of the "mac" top-level key:

// In `config/iocd.cli.config.json`.
{
    "mac": {
        "notarization": {
            "type": "notarytool",
            "appleId": "${MAC_NOTARIZATION_APPLE_ID}",
            "appleIdPassword": "${MAC_NOTARIZATION_APPLE_ID_PASSWORD}",
            "appleTeamId": "${MAC_NOTARIZATION_APPLE_TEAM_ID}"
        }
    }
}

⚠️ Note that when configuring your notarization settings, you should consider the following:

  • Notarization is required for distribution outside the Mac App Store.
  • Use an app-specific password (not your regular Apple ID password).
  • Generate an app-specific password at appleid.apple.com.
  • You can set "type" to "off" to skip notarization (for development builds).
  • Custom Script

For advanced notarization scenarios, you can provide a custom notarization script:

{
    "mac": {
        "notarization": {
            "type": "custom",
            "customNotarizationScriptPath": "path/to/custom-notarize.js"
        }
    }
}

Your custom script should export a function that receives the app bundle path and config:

// custom-notarize.js
module.exports = async function(appBundlePath, config) {
    // Your custom notarization logic here.
    console.log(`Notarizing ${appBundlePath}`);
    // Use any notarization tool or API you need.
};

Install Tasks

Available since io.Connect Desktop 10.0.4

io.Connect Desktop supports executing custom install and uninstall tasks via command-line triggers, allowing automated execution of scripts and commands during installation and uninstallation processes on both Windows and macOS.

This feature enables you to:

  • Copy configuration files to system locations after installation
  • Register protocol handlers after installation
  • Download additional resources after installation
  • Clean up user data and configurations before uninstallation
  • Unregister protocols or file associations before uninstallation
  • Backup user preferences before uninstallation

Overview

When using installers built with the seed project, io.Connect Desktop automatically responds to installation lifecycle events through command-line arguments. The Squirrel installer (used on Windows) automatically passes these arguments to the executable during install/uninstall operations.

The following command-line arguments trigger task execution:

Argument Platform Description
--post-install Cross-platform Execute install tasks (manual trigger).
--pre-uninstall Cross-platform Execute uninstall tasks (manual trigger).
--squirrel-install Windows Initial installation (triggered by Squirrel installer).
--squirrel-uninstall Windows Application uninstall (triggered by Squirrel installer).
--squirrel-updated Windows Application update (triggered by Squirrel installer).

ℹ️ The --post-install and --pre-uninstall flags can be used if you aren't using a Squirrel-based installer or if you want to manually test the install tasks.

Example:

# Windows
io-connect-desktop.exe --post-install

# macOS
open -a "io.Connect Desktop" --args --post-install

Configuration

Install and uninstall tasks are defined in platform-specific JSON configuration files within the install/ folder:

  • tasks.win32.json - Windows tasks
  • tasks.darwin.json - macOS tasks

Platform values:

  • win32 - Windows
  • darwin - macOS

File location depends on the deployment method:

  • Packaged Windows: [iocd-exe-directory]/install/ (next to the .exe)
  • Packaged macOS: IocdApp.app/Contents/install/ (in the Contents folder)

To add install tasks to your seed project, create the task files in the modifications/build/iocd/install/ directory:

modifications/
└── build/
    └── iocd/
        └── install/
            ├── tasks.win32.json  (Windows)
            └── tasks.darwin.json (macOS)

This ensures that the task files are included in your production build.

Task Schema

The task files follow this structure:

{
  "installTasks": [
    {
      "type": "run",
      "args": {
        "filename": "path/to/executable",
        "args": "command line arguments",
        "dir": "working/directory",
        "hide": true,
        "unattended": false,
        "exitCode0": "success",
        "exitCode1": "Custom error message",
        "exitCodeN": "success"
      }
    }
  ],
  "uninstallTasks": [
    {
      "type": "run",
      "args": { /* same structure */ }
    }
  ]
}

Each task supports the following properties:

Property Type Description
filename string Required. Path to the executable or script to run. Supports environment variable expansion (e.g., %TEMP%, %APPDATA%).
args string Command-line arguments to pass to the executable. The full command is passed to the system shell for parsing.
dir string Working directory for the process. Defaults to the install folder if not specified. Supports environment variables.
hide boolean Hide the process window (Windows only). Default: false.
unattended boolean Suppress error dialogs. If true, errors are logged only. Default: false.
exitCode0 to exitCodeN string Custom exit code handling. Use "success" to mark a non-zero exit code as success, or provide a custom error message. Default: exit code 0 is success, any other is an error.

⚠️ Important: Task execution is synchronous and sequential. Tasks run one at a time in the order defined. If any task fails (non-zero exit code without a success mapping), execution stops immediately and no subsequent tasks run.

Examples

Windows Batch Script
{
  "installTasks": [
    {
      "type": "run",
      "args": {
        "filename": "cmd.exe",
        "args": "/c copy-resources.bat",
        "hide": true,
        "exitCode0": "success",
        "exitCode1": "Error copying resources."
      }
    }
  ],
  "uninstallTasks": [
    {
      "type": "run",
      "args": {
        "filename": "cmd.exe",
        "args": "/c cleanup.bat",
        "hide": true
      }
    }
  ]
}
macOS Shell Script
{
  "installTasks": [
    {
      "type": "run",
      "args": {
        "filename": "/bin/bash",
        "args": "setup.sh --silent",
        "hide": false
      }
    }
  ],
  "uninstallTasks": [
    {
      "type": "run",
      "args": {
        "filename": "/bin/bash",
        "args": "cleanup.sh",
        "dir": "/tmp"
      }
    }
  ]
}
Custom Exit Code Mapping

You can map specific exit codes to success or custom error messages:

{
  "installTasks": [
    {
      "type": "run",
      "args": {
        "filename": "installer.exe",
        "args": "--verify",
        "exitCode0": "success",
        "exitCode1": "Error validating the installation.",
        "exitCode2": "Error contacting server.",
        "exitCode3": "success",
        "exitCode4": "Network timeout - please retry."
      }
    }
  ]
}

In this example:

  • Exit codes 0 and 3 are considered successful
  • Exit codes 1, 2, and 4 will show custom error messages
  • Any other exit code will show a default error message

Environment Variable Expansion

All path-related properties (filename, args, dir) support environment variable expansion using the %VAR% syntax:

{
  "args": {
    "filename": "%APPDATA%\\MyCompany\\install-script.bat",
    "dir": "%LOCALAPPDATA%\\MyCompany"
  }
}

Platform-Provided Variables

The following environment variables are automatically set by io.Connect Desktop and available for use in all install tasks:

Variable Description Example Value
IO_CD_EXE_NAME Executable file name io-connect-desktop.exe (Windows)
io-connect-desktop (macOS)
IO_CD_ROOT_DIR Root installation directory C:\Users\...\io-connect-desktop\app-10.0.4 (Windows)
/Applications/io.Connect Desktop.app/Contents (macOS)
IO_CD_INSTALL_DIR Directory containing install tasks C:\Users\...\io-connect-desktop\app-10.0.4\install (Windows)
/Applications/io.Connect Desktop.app/Contents/install (macOS)

Troubleshooting

Tasks not executing:

  • Verify that the install/tasks.win32.json (Windows) or install/tasks.darwin.json (macOS) file exists in the correct location
  • Check that the file contains valid JSON
  • Ensure the executable paths are correct and accessible

Tasks failing:

  • Review the console logs for error messages
  • Test the script manually to verify it works
  • Check file permissions (especially on macOS - scripts need execute permission)
  • Verify environment variables are correctly expanded

Silent installation fails:

  • Ensure all tasks have "unattended": true to prevent error dialogs
  • Test each task individually to identify which one is failing
  • Consider adding custom exit code mappings for expected error conditions

CI/CD Automation

Continuous Integration and Continuous Deployment (CI/CD) automates building, testing, and publishing your io.Connect Desktop platform. The seed project includes a GitHub Actions workflow located in .github/workflows/build.yml. It produces signed installers and can publish them to a release server.

Auto Updates

Setting up auto updates allows your users to automatically receive new versions of your platform.

Requirements:

Auto-updates are supported for specific build artifact types:

  • Windows: Squirrel.Windows installers (.exe setup files)
  • macOS: DMG on macOS

Other build outputs (portable ZIP on Windows, ZIP on macOS) do not support automatic updates.

Update Source Types

io.Connect Desktop supports two types of update sources:

  1. StaticStorage (Simple - No Special Server Required)

This is the simpler approach that does not require a special update server. You only need a static file server (such as a CDN, web server, or cloud storage) where the RELEASES files can be accessed via HTTP/HTTPS.

How It Works:

  • macOS: The platform appends /RELEASES.json to your baseUrl and expects a JSON file with update metadata
  • Windows: The platform uses the baseUrl directly and expects a Squirrel.Windows RELEASES file at that location

Example Configuration:

Create or modify modifications/base/iocd/config/system.json.merge:

{
    "autoUpdater": {
        "enabled": true,
        "updateSource": {
            "type": "StaticStorage",
            "baseUrl": "https://cdn.yourcompany.com/updates"
        },
        "updateIntervalMinutes": 60
    }
}

With this configuration:

  • macOS will check: https://cdn.yourcompany.com/updates/RELEASES.json
  • Windows will check: https://cdn.yourcompany.com/updates (for the RELEASES file)

When to Use:

  • You want a simple deployment without maintaining a dedicated update service
  • You have a static file server, CDN, or cloud storage (e.g., AWS S3, Azure Blob Storage, GitHub Pages)
  • You don't need dynamic routing based on channels or complex version logic
  1. Service (Advanced - Requires Update Service)

This approach requires a dedicated update service that can handle dynamic routing based on platform, version, and channel.

How It Works:

The platform constructs a dynamic URL in the format: <baseUrl>/update/<platform>/<version>/<channel>

Example Configuration:

Create or modify modifications/base/iocd/config/system.json.merge:

{
    "autoUpdater": {
        "enabled": true,
        "updateSource": {
            "type": "Service",
            "baseUrl": "https://updates.yourcompany.com",
            "channel": "stable"
        },
        "updateIntervalMinutes": 60
    }
}

With this configuration, the platform will check URLs like:

  • https://updates.yourcompany.com/update/darwin/1.0.0/stable (macOS)
  • https://updates.yourcompany.com/update/win32/1.0.0/stable (Windows)

When to Use:

  • You need different update channels (stable, beta, dev)
  • You want server-side logic for update eligibility (e.g., phased rollouts, A/B testing)
  • You need to track update requests or analytics
  • You're already using an update service like Nucleus, Hazel, or a custom solution

Setting Up Auto Updates

Execute the following steps to set up platform auto updates:

  • Using StaticStorage (Recommended for Most Users)

StaticStorage supports two approaches: automated publishing with Electron Forge publishers (recommended), or manual file management (advanced).

Approach 1: Automated with Electron Forge Publishers (Recommended)

This approach uses Electron Forge publishers to automatically upload installers and generate RELEASES files.

  1. Choose your hosting platform:
  1. Configure the publisher in config/forge.config.js:

Example: S3 Publisher

module.exports = {
  publishers: [
    {
      name: '@electron-forge/publisher-s3',
      config: {
        bucket: 'my-app-updates',
        region: 'us-east-1',
        public: true,
        // Credentials via AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY env vars
      }
    }
  ],
  makers: [
    {
      name: '@electron-forge/maker-squirrel',
      config: {
        // For Windows delta updates
        remoteReleases: 'https://my-app-updates.s3.amazonaws.com'
      }
    },
    {
      name: '@electron-forge/maker-zip',
      config: {
        // For macOS RELEASES.json generation
        macUpdateManifestBaseUrl: 'https://my-app-updates.s3.amazonaws.com/darwin/x64'
      }
    }
  ]
};

Example: GitHub Publisher

module.exports = {
  publishers: [
    {
      name: '@electron-forge/publisher-github',
      config: {
        repository: {
          owner: 'your-org',
          name: 'your-repo'
        },
        prerelease: false
      }
    }
  ]
};

Important: The macUpdateManifestBaseUrl option requires using an Electron Forge publisher (like S3 or GitHub). It will not work with purely manual file uploads.

  1. Configure io.Connect Desktop to check for updates:

Create or modify modifications/base/iocd/config/system.json.merge:

{
    "autoUpdater": {
        "enabled": true,
        "updateSource": {
            "type": "StaticStorage",
            "baseUrl": "https://my-app-updates.s3.amazonaws.com"
        },
        "updateIntervalMinutes": 60
    }
}
  1. Build and publish:
npm run build

The build process will:

  • Generate installers and RELEASES files
  • Automatically upload everything to your configured publisher
  • Update the RELEASES.json with the new version (macOS)
  1. Test the auto updates:
  • Install your platform using the published installer
  • Publish a new version
  • Launch the platform and verify it detects and installs the update

Approach 2: Manual File Management (Advanced)

If you cannot use an Electron Forge publisher, you can manually manage files. This requires understanding the RELEASES file formats.

Windows: The Squirrel.Windows maker automatically generates:

  • {ProductName} Setup.exe - The installer
  • {ProductName}-full.nupkg - The full package
  • RELEASES - The update metadata file

Simply upload these files to your hosting location. The RELEASES file is plain text with nupkg metadata.

macOS: For macOS without a publisher, you must manually create and maintain the RELEASES.json file. The format is:

{
  "currentRelease": "1.0.0",
  "releases": [
    {
      "version": "1.0.0",
      "updateTo": {
        "version": "1.0.0",
        "pub_date": "2024-01-15T10:00:00Z",
        "notes": "Initial release",
        "name": "1.0.0",
        "url": "https://cdn.yourcompany.com/updates/MyApp-1.0.0-mac.zip"
      }
    }
  ]
}

Each time you release a new version, manually update this file to add the new release entry and update currentRelease.

Manual Upload Steps:

  1. Build installers: npm run build
  2. Find generated files in dist/ or out/ directory
  3. For Windows: Upload RELEASES, .exe, and .nupkg files
  4. For macOS: Create/update RELEASES.json manually and upload with .zip file
  5. Ensure all URLs in RELEASES files are accessible
  6. Test updates by installing the platform and verifying it detects new versions
  • Using Service (Advanced)
  1. Set up an update service:

You can use existing solutions or build your own:

  • Existing services: Nucleus, Hazel, or other update servers (see Electron update services)
  • Custom solution: Build your own update server that responds to requests at <baseUrl>/update/<platform>/<version>/<channel>
  1. Configure io.Connect Desktop to check the update service:

Create or modify modifications/base/iocd/config/system.json.merge:

{
    "autoUpdater": {
        "enabled": true,
        "updateSource": {
            "type": "Service",
            "baseUrl": "https://updates.yourcompany.com",
            "channel": "stable"
        },
        "updateIntervalMinutes": 60
    }
}
  1. Publish updates to your service:

Choose one of the following approaches:

Automatic publishing during build - configure publishers in config/forge.config.js:

module.exports = {
    publishers: [
        {
            name: "@electron-forge/publisher-electron-release-server",
            config: {
                baseUrl: "https://updates.yourcompany.com",
                username: process.env.RELEASE_SERVER_USERNAME,
                password: process.env.RELEASE_SERVER_PASSWORD
            }
        }
    ]
};

Manual upload - after building, manually upload the installer artifacts to your update service using its API or admin interface.

  1. Test the auto updates:
  • Install your platform using the signed installer
  • Publish a new version to your update service
  • Launch the platform and verify it detects and installs the update

CLI

The io.Connect CLI is available via the @interopio/iocd-cli library, which provides various commands for creating and manipulating a seed project for io.Connect Desktop.

To install the library, execute the following command:

npm install -g @interopio/iocd-cli@latest

You can also use npx to directly execute package commands without global installation of the package:

npx @interopio/iocd-cli@latest create

Some of the commands are defined under the "scripts" property of the package.json file of the io.Connect CLI package and can be executed via npm:

# Invokes `iocd dev`.
npm run dev

# Invokes `iocd test`.
npm run test

# Invokes `iocd setup`.
npm run setup

# Invokes `iocd build`.
npm run build

# Invokes `iocd build --skip-install`.
npm run build-skip-install

# Invokes `iocd apps dev`.
npm run apps-dev

# Invokes `iocd components install`.
npm run components-install

Commands

The io.Connect CLI offers the following main commands:

Command Description
apps Command with sub-commands for managing the customizable system apps in the seed project.
build <options> Builds and packages the io.Connect Desktop platform for distribution.
components Command with sub-commands for managing the seed project components.
create <options> Creates a new seed project. Accepts options for configuring the seed project.
dev Starts io.Connect Desktop in development mode (the platform isn't packaged yet).
help <command> Displays help for the specified command.
license Displays current license key information.
modifications Command with sub-commands for managing the seed project modifications.
setup Prepares the seed project for first usage. This will install the specified components and will install the dependencies for all customizable system apps.
test Runs the test suite.

create

The create command accepts the following options:

Option Description
--source <url/path> Override component source during setup
--non-interactive Run in non-interactive mode using provided options
--product-name <name> Product name for non-interactive mode
--folder-name <name> Folder name for non-interactive mode
--components <components> Comma-separated list of components (e.g., "iocd,demos,devTools")
--applications <applications> Comma-separated list of apps (e.g., "groups,workspaces")
--license-key <key> License key for non-interactive mode
--use-current-folder Install in current folder (non-interactive mode)
-h, --help Display help for command

build

The build command accepts the following options:

Option Description
--output <path> Output directory for packages (default: "dist/packages")
--publish-only Skip the build phase and only publish packages (does nothing if no publish is configured) (default: false)
--skip-install Skip installing components during the build process (default: false)
-h, --help Display help for command

components

The components command has the following sub-commands:

Command Description
uninstall <name> Remove a component from the project
install [name] Install all components listed in iocd.cli.config.json or a specific component by name
list List all installed components
browse Browse all available components from currently selected store
pin Pin all "latest" component versions to their current specific versions for reproducible builds
download [options] [output-dir] Download all available components (including prereleases) for all platforms from the current store to a local directory in local store format (-f, --force Overwrite existing files without prompting)
help [command] Display help for command

apps

The apps command has the following sub-commands:

Command Description
install [options] Install dependencies for all template apps
build [options] Build all template apps and copy output to modifications folder. Requires prior installation of dependencies.
dev [options] Start all template apps in development mode
list List all template apps that are added to the seed project, and all available templates
add <appName> Add a new template app from the registry
help [command] Display help for command

modifications

The modifications command has the following sub-commands:

Command Description
apply [component] Apply all modifications or modifications for specific component
help [command] Display help for command

Troubleshooting

This guide addresses common issues when running the io.Connect Desktop CLI

1. Node.js SSL/TLS Certificate Errors

Symptoms:

  • SELF_SIGNED_CERT_IN_CHAIN errors
  • unable to verify the first certificate
  • CLI cannot connect to GitHub or npm registry

Root Cause: Corporate proxies often intercept HTTPS traffic and re-sign requests with an internal certificate. Node.js doesn't trust these certificates by default, causing HTTPS requests to fail.

Solutions:

Starting from Node.js 24, Node uses the operating system's trust store. If your corporate certificate is already trusted by your OS (which is usually the case), no manual configuration is needed.

# Check your Node.js version
node --version

# If below v24, upgrade Node.js

For Node.js 24+, you can also explicitly enable system certificates:

Windows (PowerShell - current session):

$env:NODE_OPTIONS = "--use-system-ca"
npm run setup

Windows (PowerShell - permanent for current user):

[Environment]::SetEnvironmentVariable("NODE_OPTIONS", "--use-system-ca", "User")
# Restart your terminal for changes to take effect

macOS/Linux (current session):

NODE_OPTIONS="--use-system-ca" npm run setup

macOS/Linux (permanent):

# Add to your shell profile (~/.zshrc or ~/.bashrc)
echo 'export NODE_OPTIONS="--use-system-ca $NODE_OPTIONS"' >> ~/.zshrc
source ~/.zshrc

Option B: Disable TLS Verification (Development Only)

⚠️ Warning: This disables security checks. Use only in development environments.

Windows (PowerShell - current session):

$env:NODE_TLS_REJECT_UNAUTHORIZED = "0"
npm run setup

Windows (PowerShell - permanent for current user):

[Environment]::SetEnvironmentVariable("NODE_TLS_REJECT_UNAUTHORIZED", "0", "User")
# Restart your terminal for changes to take effect

macOS/Linux (current session):

NODE_TLS_REJECT_UNAUTHORIZED=0 npm run setup

macOS/Linux (permanent - not recommended):

echo 'export NODE_TLS_REJECT_UNAUTHORIZED=0' >> ~/.zshrc
source ~/.zshrc

2. Node.js Proxy Configuration Issues

Symptoms:

  • npm run setup fails with network errors
  • GitHub API requests fail even though the browser can access GitHub
  • ECONNREFUSED or timeout errors
  • CLI cannot download components from GitHub
  • "Network error: fetch failed" with retries

Root Cause: Node.js does not automatically use system proxy settings (WinHTTP on Windows, system preferences on macOS). Even if your browser works behind a proxy, Node.js applications need explicit proxy configuration.

Solution:

The CLI (version 0.0.54+) automatically detects and uses your system proxy settings. If you're experiencing proxy-related issues, ensure you're running the latest version of the CLI:

npm i @interopio/iocd-cli@latest

After updating, run the setup command again. The CLI will automatically route requests through your system's configured proxy.

Verification:

If you want to verify your proxy settings are correctly configured at the system level:

Windows (PowerShell):

# Check system proxy (WinHTTP)
netsh winhttp show proxy

# Test if GitHub API is reachable
curl https://api.github.com/repos/interopio/iocd-components/releases?per_page=1

macOS/Linux:

# Check network configuration
scutil --proxy

# Test connectivity
curl -I https://api.github.com

If the browser/curl works but the CLI still fails after updating, there may be a TLS certificate issue (see next section).

3. npm Registry Errors

Symptoms:

  • E400 Bad Request when installing packages
  • npm error 400 Bad Request - GET https://registry.npmjs.org/@interopio%2f...
  • Timeouts when downloading npm packages

Root Cause: npm uses its own SSL policy and doesn't automatically inherit Node.js TLS settings. Corporate proxies may also block or interfere with npm registry requests.

Solutions:

Disable npm Strict SSL

npm config set strict-ssl false

Configure Corporate npm Registry

If your organization has an internal npm registry or proxy:

# Set your corporate registry
npm config set registry https://your-corporate-registry.com/

# Or use a scoped registry for @interopio packages
npm config set @interopio:registry https://registry.npmjs.org/

View Current npm Configuration

npm config get registry
npm config list

4. npm Proxy Configuration

Symptoms:

  • npm install fails with ECONNREFUSED or timeout errors
  • Package downloads hang or fail while CLI operations (like downloading components) work fine
  • npm ERR! network errors during dependency installation

Root Cause: The CLI uses its own HTTP client with automatic proxy support from environment variables. However, npm has its own network stack and may not inherit these settings. npm requires explicit proxy configuration through its own config system.

Solution:

The CLI automatically uses proxy settings from HTTP_PROXY/HTTPS_PROXY environment variables for its own network operations (downloading components from GitHub). However, npm package installations are handled by npm itself, which may need separate proxy configuration:

npm config set proxy http://your-proxy-server:port
npm config set https-proxy http://your-proxy-server:port

Note: In most enterprise environments, IT departments already configure HTTP_PROXY/HTTPS_PROXY environment variables system-wide. If these are set, the CLI will use them automatically. Check with your IT team if you're unsure whether these are configured.

5. Build fails with "License not found":

  • Ensure that the IOCD_LICENSE_KEY environment variable is set or create an iocd.license.key file in the /config folder with your license key.

6. Code signing fails on Windows:

  • Verify that the certificate is valid and not expired.
  • Check that "pfxPassword" is set correctly.
  • Verify that exactly one of "pfxPath" or "certificateSha1" is configured (not both).

7. Notarization for macOS fails:

  • Use an app-specific password, not a regular Apple ID password.
  • Generate an app-specific password at appleid.apple.com.
  • Verify that your Apple Developer Program membership is active.
  • Ensure that "appleTeamId" matches your Developer Team ID.

8. The platform won't start in development mode:

  • Run npm run setup to verify component installation.
  • Verify that that the components/iocd directory exists.
  • Review the logs in the system /temp directory.

9. Components not downloading:

  • Verify network connectivity.
  • Verify the component store configuration in the iocd.cli.config.json file located in the /config folder.
  • For GitHub stores: ensure that the repository access and credentials are correct.

CLI Changelog

0.0

0.0.74

Release date: 02.03.2026

New Features

  • Add excludeFolders option for Windows code signing — allows specifying glob patterns to exclude folders from code signing. Supports **, *, ? wildcards and ! negation patterns (last matching pattern wins). By default, no folders are excluded.

0.0.73

Release date: 27.02.2026

New Features

  • Skip code signing for binaries that are already signed, reducing build time and avoiding re-signing issues.

Improvements & Bug Fixes

  • Apply npm audit fixes to test template package-lock files to resolve security vulnerabilities.

0.0.72

Release date: 30.01.2026

New Features

  • Register adapter components (bbg-mdf, excel, fidessa, outlook, word) in the CLI component registry with platform support metadata.

0.0.71

Release date: 29.01.2026

New Features

  • Add array merge directives ($replace, $prepend, $append, $remove) for .json.merge files, giving fine-grained control over how arrays are combined during modifications.

0.0.70

Release date: 27.01.2026

Improvements & Bug Fixes

  • Trigger a version.

0.0.69

Release date: 22.01.2026

New Features

  • Enable cross-compilation of Windows installers on Linux by adding rcedit support and removing platform-specific OS calls.

0.0.68

Release date: 21.01.2026

Improvements & Bug Fixes

  • Change platform default to win32 for components (was darwin).

0.0.67

Release date: 21.01.2026

Improvements & Bug Fixes

  • Change platform default to win32 for components (was darwin).

0.0.66

Release date: 14.01.2026

Improvements & Bug Fixes

  • Fix Windows executable icon patching to source the icon from the modifications folder instead of the default location.

0.0.65

Release date: 13.01.2026

Improvements & Bug Fixes

  • Fix modification tracker so that deleting a modification source file correctly removes the corresponding output file from the component.

0.0.64

Release date: 10.01.2026

Improvements & Bug Fixes

  • Replace OS-specific shell-based ZIP extraction (PowerShell on Windows, unzip on macOS) with the cross-platform extract-zip npm package.

0.0.63

Release date: 09.01.2026

New Features

  • Read entitlements.mac.plist and .nuspectemplate from the CLI. These files were previously in the templates dir, now are bundled with the CLI and read from there. This allows easier updates and less confusion when users create new projects.

0.0.62

Release date: 05.01.2026

New Features

  • Support for specifying a custom tests directory in the CLI configuration.

0.0.60

Release date: 31.12.2025

New Features

  • Automatically reset all modifications before running dev or build commands to ensure a clean state.
  • Display notification when a newer version of the CLI is available.

Improvements & Bug Fixes

  • Relaxed config schema validation to allow partial configuration files.
  • Updated .gitignore handling to only ignore the top-level components folder, not nested ones.

0.0.59

Release date: 12.12.2025

New Features

  • Support passing additional arguments to the Electron process in dev mode.
  • New --output argument for the build command to specify a custom output directory.
  • Export CLI commands for use as a library in other projects.

Improvements & Bug Fixes

  • Automatically install dependencies when adding new apps to a project.
  • Updated Launchpad Vite configuration for improved build performance.

0.0.57

Release date: 09.12.2025

New Features

  • Auto include tests when setting up a new project with create command.

0.0.56

Release date: 06.12.2025

Improvements & Bug Fixes

  • Improved error logging message.

0.0.55

Release date: 06.12.2025

Improvements & Bug Fixes

  • Fix for versions that contain a letter in the build timestamp.

0.0.54

Release date: 04.12.2025

New Features

  • Add HTTP/HTTPS proxy support for all CLI network requests, enabling use behind corporate proxies and firewalls.

0.0.53

Release date: 01.12.2025

New Features

  • Log Node.js and CLI versions at the beginning of each log file for easier debugging.

0.0.52

Release date: 30.11.2025

New Features

  • Register the Bloomberg (BBG) component in the CLI component registry for download and inclusion in builds.

0.0.51

Release date: 28.11.2025

New Features

  • Add an overwrite mode for component modifications, allowing files to completely replace targets instead of being merged.

0.0.49

Release date: 26.11.2025

Improvements & Bug Fixes

  • Change configs to rely on package.json where possible.
  • Add UI version.
  • Updates in wdio.config for tests.
  • Fix for eslint setup.

0.0.43

Release date: 20.11.2025

New Features

  • Support variable substitution of product slug and product name in modification files, enabling dynamic per-product configuration.

0.0.42

Release date: 20.11.2025

New Features

  • Add OS-specific modification folders (modifications-win32, modifications-darwin) so different platforms can have distinct configuration overrides.
  • Embed product version in the Windows setup executable filename.

Improvements & Bug Fixes

  • Various fixes; fix build.

0.0.35

Release date: 16.11.2025

Improvements & Bug Fixes

  • Update Node.js requirement to 22.0.0.
  • Minor fix.

0.0.33

Release date: 16.11.2025

Improvements & Bug Fixes

  • Updated README.
  • Simplify config.
  • Changed pfx to signtool.

0.0.29

Release date: 13.11.2025

New Features

  • Enable shell mode for child process execution to support system PATH resolution.

0.0.28

Release date: 13.11.2025

Improvements & Bug Fixes

  • Using signtool for signing; remove explicit digicert support.

0.0.27

Release date: 10.11.2025

New Features

  • Add license.copyLicenseToOutput config option to automatically include the license file in the build output.

0.0.26

Release date: 06.11.2025

New Features

  • Add end-to-end test infrastructure for CLI commands.
  • Add license file handling and validation.
  • Add JSON schema for CLI configuration file (iocd.cli.config.json) validation.

0.0.24

Release date: 30.10.2025

New Features

  • Add end-to-end test support with small improvements.
  • Basic test scaffolding.
  • Download all components.

0.0.23

Release date: 15.10.2025

Improvements & Bug Fixes

  • Logger fix.
  • Setup Apple code-signing.

0.0.22

Release date: 13.10.2025

Improvements & Bug Fixes

  • Fix icons and ability to sign using certificate on Mac.

0.0.20

Release date: 12.10.2025

New Features

  • Automatically generate and manage .gitignore files for new projects.

0.0.18

Release date: 12.10.2025

New Features

  • Allow the create command to initialize a project in the current directory if it is empty.

0.0.17

Release date: 12.10.2025

New Features

  • Add build configuration templates for Windows and macOS installers.

0.0.15

Release date: 11.10.2025

New Features

  • Add --skip-components CLI flag to the build command, allowing builds without downloading or updating components.

0.0.14

Release date: 11.10.2025

Improvements & Bug Fixes

  • Add GitHub token to the GitHub request.

0.0.9

Release date: 09.10.2025

New Features

  • Add support for top-level modifications that apply across all components, in addition to per-component modifications.

0.0.6

Release date: 07.10.2025

New Features

  • Integrate Sentry error tracking for automatic crash reporting and diagnostics.
  • Add internal presentation materials.

0.0.4

Release date: 04.10.2025

New Features

  • Pin component versions after initial project setup to ensure reproducible builds.
  • Add per-component modification folders (modifications-xxx) for targeted config overrides.
  • Auto-update support with system.json.merge template generation.

0.0.3

Release date: 28.09.2025

New Features

  • Added demos component support.
  • Add flag for prerelease.
  • Added doc about components storage.

0.0.2

Release date: 26.09.2025

New Features

  • License checks.
  • Licensing.

0.0.1

Release date: 22.09.2025

New Features

  • Initial release.
  • CLI project setup with create command.
  • Components selection in the create phase.
  • Ability to add apps.
  • S3 support for components storage.
  • Local storage support with same structure as S3.
  • Launchpad component.
  • Components remove functionality.
  • Installer/build command for Windows and macOS.
  • Code signing support for macOS and Windows.
  • Splash screen template.
  • Auto-update configuration support.
  • GitHub workflow for CI/CD.