Desktop packages
Desktop packaging takes the shared Fission app and gives it the operating-system metadata users expect: name, icon, bundle identity, installer shape, signing references, and a predictable artifact manifest.
Use this page for the shared desktop lifecycle. Use the platform pages when you
are filling in real release values:
| |
|---|
| |
macOS app extensions or system extensions | |
| |
| |
1. Check the desktop target
Start with readiness. It catches missing target setup and packaging tools before the release build starts.
fission readiness package --project-dir . --target macos --format app
fission readiness package --project-dir . --target windows --format msix
fission readiness package --project-dir . --target linux --format run
Readiness should confirm the target exists in fission.toml, the app has usable icons, the package identity is present, and the platform tools needed for the selected format are available. | | |
|---|
| | Local app-bundle validation and direct distribution. |
| | Installer-based distribution and managed deployment. |
| | Signed executable, or a project-defined offline installer flow. |
| | Enterprise or managed Windows installer flow. |
| | Microsoft Store and modern Windows package identity workflows. |
| | Self-contained Linux installer artifact. |
Use the smallest format that proves the next step. For example, use .app while validating icon, dock, and permission behavior on macOS; move to .pkg when installer behavior matters.
3. Build the package
fission package --project-dir . --target macos --format app --release
fission package --project-dir . --target macos --format pkg --release --variant scanner
The package command writes the platform artifact and an artifact-manifest.json under target/fission/release/<target>/<format>/. Use that manifest for release commands instead of passing a raw file path.
Apps with several native product shapes can declare module membership with
variants = ["scanner"] or another stable lowercase name on each
[[native.modules]] entry. A selected variant includes matching modules and
modules with no restriction. Restricted modules are excluded when no variant is
selected. Variant artifacts are written below
target/fission/<profile>/<target>/<format>/variants/<name>/, and custom
packager scripts receive the same name as FISSION_VARIANT.
Run with --json in CI when a downstream job needs to discover the manifest
path or primary artifact without scraping console output:
fission package --project-dir . --target windows --format msix --release --json
The manifest is the only handoff the release workflow should need. It records
target, format, package profile, hashes, sizes, validation checks, source
configuration hashes, signing/notarization facts where available, and any
secondary artifacts such as symbols or crash diagnostics.
Keep production macOS signing in the release overlay:
[package.macos]
bundle_id = "com.example.app"
team_id = "ABCDE12345"
[package.macos.release]
entitlements = "platforms/macos/Distribution.entitlements"
signing_identity = "Developer ID Application: Example Ltd"
installer_identity = "Developer ID Installer: Example Ltd"
notarize = true
The nested values are ignored for debug packages. With release notarization
enabled, Fission signs the .app, creates a private temporary ditto ZIP for
notarytool, and staples and validates the original app. A .pkg build embeds
that stapled app, signs the installer, then notarizes, staples, and validates the
.pkg as before. Temporary submission archives and environment-provided key
material are removed when each operation finishes.
4. Add native products when the package needs them
For macOS apps with native extensions, declare the Xcode project and products
under [[native.modules]] in fission.toml. Fission builds the native schemes,
embeds app extensions and system extensions in their platform-defined bundle
locations, signs those nested products, and signs the containing app last. The
same declaration is used by fission build, fission test, fission run, and
fission package; app-specific build scripts should not duplicate that work.
Linux Cargo-native products use [native.modules.linux]. Fission builds and
tests the declared package, stages runtime files and privileged helpers into
development and package roots, and embeds a digest-bearing native-products
manifest in Linux .run payloads. privileged-helper is packaging metadata;
Fission never silently adds setuid bits, capabilities, or an elevation policy.
The application installer remains responsible for an explicit, auditable
privilege transaction.
Windows MSBuild/WDK products use [native.modules.windows]. Runtime products
are staged beside the app for local runs and are exposed to package scripts in a
structured native-products manifest. Products marked driver-package are
installer inputs and are deliberately excluded from MSIX manifests. Configure
package.windows.exe_installer_script when windows/exe must produce a setup
program rather than stage the application executable itself. Set
nuget_packages_config and nuget_packages_directory when the native project
pins the supported WDK NuGet packages; Fission restores them non-interactively
before every MSBuild invocation.
For a complete field-by-field guide, use
Native modules. The practical rule is
that native products are normal release inputs, not hidden build script side
effects. If the app needs them at runtime, declare them as runtime products. If
an installer needs them but the app should not load them directly, classify them
as driver-package or privileged-helper. 5. Use installer scripts only at the installer boundary
Fission can create simple desktop package artifacts itself, but some products
need a real installer: drivers, services, privileged helpers, repair/uninstall
behavior, or machine-level integration. Use the package script hooks for those
cases.
Linux .run package script:
[package.linux.run]
installer_script = "platforms/linux/package-run.sh"
The script receives FISSION_LINUX_PAYLOAD_DIR, LINUX_BINARY,
FISSION_LINUX_NATIVE_PRODUCTS_MANIFEST, and LINUX_PROFILE on release builds.
It prints the completed .run path on stdout.
Windows .exe installer script:
[package.windows]
exe_installer_script = "platforms/windows/package-exe.ps1"
The script receives WINDOWS_BINARY,
FISSION_WINDOWS_NATIVE_PRODUCTS_MANIFEST, and WINDOWS_PROFILE on release
builds. It prints the completed .exe path on stdout.
Keep installer scripts deterministic. They should consume the staged package
inputs, create one installer artifact, and let Fission record the final artifact
in artifact-manifest.json.
6. Verify the result
Open or install the produced package on the target operating system. Check the app name, icon, dock or taskbar behavior, permission prompts, window title, and any capability the app needs. Packaging is not complete until the installed app behaves like an app, not like an unnamed development binary.
Next steps