Build a polished installer without giving up control.
A modern Studio, deterministic packages, transactional updates, and one Rust core for Windows, Linux, and macOS.
Rust 1.96 · Tauri 2 · React 19 · Apache-2.0 OR MIT
Quick start · Automation · Platform status · Architecture · Security · Contributing
Important
Luxury Installer is a functional development preview, not a production release. The core package and user-scope lifecycle work today. Final signed Windows evidence, installed and distribution-signed Linux helper evidence, signed/notarized macOS evidence, and a downloaded three-host release matrix are still required.
Open Studio and describe the application instead of hand-writing a setup script:
- edit identity, version, publisher, target, architecture, and install scope;
- add files or a complete folder through native dialogs;
- choose the launch file from the real payload;
- add a license, optional installation details, and up to four HTTPS finish links;
- save, revalidate, and build one deterministic
.luxpkg.
Source and output paths stay in the Rust shell. React receives validated portable settings, not generic filesystem access. Imports never overwrite an existing payload entry, and a failed partial import rolls back.
Each Setup is bound to one reviewed payload. It shows the application, publisher, version, destination, and exact operation without becoming a package browser.
- a newer downloaded version becomes an update;
- the same version with the exact file set becomes repair;
- downgrade is never silently approved;
- cancellation and failure restore the previous installation;
- unknown files and modified obsolete files are preserved;
- successful progress waits for an explicit Next before showing launch, folder, and finish-link actions;
- package authors decide whether the bounded installation-details panel is available.
There is no built-in update-download service yet. Updating means launching a newer Setup for the same package ID and roots; the transactional upgrade itself is implemented.
| Luxury Installer | |
|---|---|
| Package | Deterministic .luxpkg with strict portable paths and exact hashes. |
| Trust | Unsigned development v1, Ed25519-signed v2, authenticated publisher rotation v3. |
| Lifecycle | Read-only preflight, install, update, repair, explicit downgrade policy, rollback/recovery, uninstall, and receipt-owned launch. |
| Ownership | Receipts live outside the removable application tree. Unknown or modified data is not claimed. |
| Desktop | Fixed adaptive Codex-style Tauri window with a small exact ACL and no renderer shell/fs/process permission. |
| Build speed | Core Rust and desktop graphs are separate; routine work uses targeted gates instead of a serial native matrix. |
| Automation | Human CLI plus strict typed JSONL v3 over stdin/stdout for agents and desktop composition. |
You need:
- Rust via rustup —
rust-toolchain.tomlpins Rust1.96.0; - Node.js
22.12+and pnpm10.26.2; - the Tauri 2 prerequisites for your host OS.
Install the desktop dependencies once:
pnpm --dir apps/luxury-installer install --frozen-lockfileStart Studio:
cargo build -p luxury
pnpm --dir apps/luxury-installer run dev:appOr create and build directly from the CLI:
cargo run -p luxury -- init <project-dir>
cargo run -p luxury -- build <project-dir> <out.luxpkg>
cargo run -p luxury -- inspect <out.luxpkg>Unsigned v1 installation always needs explicit consent:
cargo run -p luxury -- prepare-install <out.luxpkg> <install-base> <state-root>
cargo run -p luxury -- install <out.luxpkg> <install-base> <state-root> --allow-unsignedKeep <state-root> outside the removable install tree. Reuse the same roots for update, repair, launch, and uninstall.
Run Setup locally with one absolute package path after Tauri's separators:
pnpm --dir apps/luxury-installer exec tauri dev -- -- --package="<absolute-package.luxpkg>"Signed development QA may append --trusted-publisher-key="<absolute-public.pem>". Release Setup ignores debug path overrides and uses only its embedded backend and bound payload.
Private signing keys are bounded PKCS#8 PEM read from stdin only:
<private-key-provider> | cargo run -p luxury -- build <v2-project> <out-v2.luxpkg> --signing-key-stdin
cargo run -p luxury -- inspect <out-v2.luxpkg> --trusted-publisher-key <public.pem>They are never accepted as an argument, JSONL field, environment setting, project value, log, or fixture. Publisher rotation keeps the current and next private keys in separate processes. See the complete CLI reference.
Every public command has safe, non-mutating subcommand help:
cargo run -p luxury -- install --help
cargo run -p luxury -- help installFor coding agents and CI clients:
llms.txtis the compact repository map;luxury-installer-cliis the reusable agent skill;- its CLI and JSONL v3 reference contains every current command, method, envelope, consent, update rule, and cancellation pattern;
docs/ai-build.mdmaps changes to the smallest useful verification gate.
The repository test derives the live JSONL method table and fails when the AI guide, llms.txt, or skill falls behind.
Use the smallest command that proves the work:
| Command | Use it for |
|---|---|
cargo quick --locked |
Normal core Rust loop. |
cargo gui-check |
Renderer contracts, strict TypeScript, Vite, and both Tauri flavors. |
cargo studio-assemble |
Payload-free Studio for the current host. |
cargo assemble -- <package.luxpkg> |
One package-bound unsigned development Setup for the current host. |
cargo runner-smoke |
Native packaged lifecycle, cancellation, recovery, launch, cleanup, and local evidence. |
Windows, Linux, and macOS have different final container/signing flows. Follow the exact order in the AI build guide; Rust release commands do not accept signing credentials.
| Platform | Implemented | Still required before release |
|---|---|---|
| Windows 10/11 | User lifecycle; source-level authenticated one-shot system prepare/install/uninstall/launch; NSIS development and two-phase release flow. | Signed-final native lifecycle and downloaded final-byte verification. |
| Linux desktop | User lifecycle; fixed root-owned helper/polkit design; deterministic tar plus inspected unsigned .deb/RPM development packages. |
Installed root-owned lifecycle, distribution signing, and removal of the GTK3 glib 0.18.5 advisory from the final graph. |
| macOS 13+ | User lifecycle; signed SMAppService helper design; deterministic app transport and DMG verification flow. |
Signed/notarized native lifecycle and final downloaded artifact proof. |
Linux desktop publication remains blocked by RUSTSEC-2024-0429 in the pinned GTK3/Wry dependency graph. The project does not hide that advisory or call the current Linux desktop artifact release-ready.
The short version:
- all manifest, archive, path, receipt, journal, JSONL, and renderer input is untrusted;
- absolute, parent, UNC/device/ADS, alias-colliding, link/reparse, and special payload entries are rejected;
- mutation starts only after verification and read-only preflight, then runs under locks, journal, rollback, and external receipt ownership;
- Setup never receives a user-selected package; one payload is bound at build time;
- system roots and package authority never come from React, argv, JSONL, or environment variables;
- launch is zero-argument and receipt-owned—no shell, forwarded environment, or automatic run.
Read SECURITY.md, the architecture, and the privileged-helper contract before changing a trust boundary. Please report vulnerabilities privately through GitHub Security Advisories.
Start with CONTRIBUTING.md. Keep changes as small vertical slices, preserve unrelated work, and report the exact gates that passed plus native/release evidence that remains unverified.
Questions belong in Discussions; reproducible defects use the issue forms. See SUPPORT.md, CHANGELOG.md, and CODE_OF_CONDUCT.md.
Licensed under either Apache License 2.0 or MIT, at your option.