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:
Platform
Detailed page
macOS
macOS app extensions or system extensions
Windows
Linux

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.

2. Choose the package format

Target
Format
Use it for
macOS
.app
Local app-bundle validation and direct distribution.
macOS
.pkg
Installer-based distribution and managed deployment.
Windows
.exe
Signed executable, or a project-defined offline installer flow.
Windows
.msi
Enterprise or managed Windows installer flow.
Windows
.msix
Microsoft Store and modern Windows package identity workflows.
Linux
.run
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

Read Release and distribute when the desktop artifact is ready to upload. For exact manifest fields, use the fission.toml reference.