For developers. WinAppMigrator is a Rust workspace of six crates, for Windows only. This page says what each crate is, how they depend on each other, and the rules that keep them apart. Code map goes file by file. The project's own rules are in CONTRIBUTING.md.
| Crate | Builds | What it is |
|---|---|---|
winappmigrator-core |
A library | All shared logic: listing apps, scanning, packaging, the installer format, restoring, verifying, the journal, and undoing |
winappmigrator-ui |
A library | The shared design system and widgets, how every window opens, and process hardening |
winappmigrator-gui |
winappmigrator.exe, the app |
The single screen that builds an installer. Never restores anything. |
winappmigrator-installer |
winappmigrator-installer.exe, the stub |
The program at the front of every installer, and every uninstaller. The only program that calls the restore code. |
winappmigrator-link |
A library | The encrypted link between the app and the client: finding clients, pairing by the code, the encrypted channel, what is asked and answered, and which paths may be asked about. Builds for Windows 7 as well as 10 and 11. |
winappmigrator-client |
winappmigrator-client.exe, which the app saves as WinAppMigrator Client.exe
|
Runs on the PC an app is moving off, Windows 7 or later. Captures nothing: takes a snapshot of the Windows drive, and answers the app's requests to describe, list, and read paths in it, read-only. One 32-bit program, built for Windows 7. |
flowchart TD
GUI["winappmigrator-gui (the app)"] --> CORE["winappmigrator-core"]
GUI --> UI["winappmigrator-ui"]
INST["winappmigrator-installer (the stub)"] --> CORE
INST --> UI
GUI -.->|carries the built stub| INST
CORE --> LINK["winappmigrator-link"]
GUI --> LINK
CLIENT["winappmigrator-client"] --> LINK
GUI -.->|carries the built client| CLIENT
The app carries the stub inside itself. Its build script embeds the stub's compiled bytes, so the app is one portable .exe, and building an installer means writing the stub, then the package, then a footer. That is why the stub must be built before the app. See Building and testing.
The app carries the client the same way, built first by scripts/build-client.ps1, for a target the rest of the workspace is not built for, and in a release, signed before the app is built around it. Of the project's crates, the client uses only winappmigrator-link.
These are the project's rules, and the layout follows from them.
-
The app builds, and the installer restores.
winappmigrator-guibuilds an installer and never restores anything. The restore code lives inwinappmigrator-core, and onlywinappmigrator-installercalls it. Nothing in the crates' dependencies enforces that: it is a rule the code keeps. Shared logic goes inwinappmigrator-core, and shared UI inwinappmigrator-ui. -
One screen, one job. The app is a single screen that produces one self-extracting
.exe, or, past the 4 GiB Windows can start, a small loader and a data file beside it. There are no other pages, no navigation, and no restore controls in it. -
Restore is a dry run until told otherwise. Nothing is installed without
--applyor the Install button. - Never sign the installer stub. See Releases and signing.
- Do not copy shared files an app does not own. Shared runtimes are reported as prerequisites, and installed by Microsoft's own installers.
- Licensing data is opt-in, and meant only for its owner. Never decrypt it, get around or imitate activation, or imitate a dongle.
-
No panics in normal flow, and no
unwraporexpect: clippy denies them, workspace-wide. -
unsafeis denied everywhere exceptwinappmigrator-ui/src/hardening.rs, which makes one Windows call that has no safe wrapper. - Logs hold paths and key names only. What a registry value, license file, or environment variable holds must never reach one. A test pins that.
-
Keep the docs true: update the README,
docs/, andCHANGELOG.mdin the same change as the code.
Both executables embed a manifest that demands administrator rights (requireAdministrator), in every build. A test harness linked into such an executable could not start from a normal shell. So each executable's main.rs only hardens the process and calls into a library, and all their logic, and its tests, live in lib.rs and the modules under it. That is also why cargo test is never run with --all-targets. See Building and testing. The client demands administrator rights too, so its tests are in its library, and its program is never built as a test harness (test = false).
The installer stub decides what it is by its command line:
| Command line | What runs |
|---|---|
Contains --uninstall (checked first) |
The uninstaller: its window (uninstall_gui.rs), or with --quiet, none (uninstall.rs) |
| No arguments | The installer's window (gui.rs) |
| Any other arguments | The headless installer (headless.rs) |
An install keeps a bare copy of the stub in its record folder, as uninstall.exe. The app's entry in Settings runs that copy with --uninstall <id>.
Roughly, by stage. Code map lists every file.
| Stage | Main files |
|---|---|
| Listing apps |
app_inventory.rs, profile_survey.rs, system_context.rs, and disk_image.rs
|
| Reading another PC over the network |
remote.rs, source_fs.rs
|
| Scanning |
scan.rs, install_source.rs, file_discovery.rs, product_match.rs, near_match.rs, registry_scan.rs, integration_scan.rs, and the other *_scan.rs files |
| Choosing | footprint.rs |
| Packaging |
package.rs, packer.rs, zip_stream.rs, archive.rs
|
| Installing |
restore.rs, restore_policy.rs, restore_review.rs, path_rewrite.rs, verify.rs
|
| Undoing |
journal.rs, rollback.rs
|
Two design points run through all of it:
-
One review.
restore_review.rsapplies the rules inrestore_policy.rsto a whole package. The app's screen, the installer's list, the install itself, and verification all go through that same review, so what a person is shown is what happens. -
One place for another PC's paths.
system_context.rsis the single way scanners read the registry and known folders, whether from this PC, a connected drive, or a disk image, andVolumeMapis the one place a path recorded on another PC becomes a path that can be read here. A PC over the network is read the same way: it gets a root of its own,\\?\WAMLINK-<id>\, andsource_fs.rssends what is read below that root to its client.
| Folder | What is in it |
|---|---|
docs/ |
Discovery, the interface, signing, and the plan with its open issues |
docs/images/ |
The README's screenshots, copied from the UI tests' previews, which the website uses too |
site/ |
The website's landing page, the frame around each page of this wiki there, and its style. See CI jobs |
scripts/ |
sign.ps1, to sign a finished installer, make-icon.ps1, which makes the window and file icon, and build-client.ps1, which builds the client for Windows 7 and later |
.github/workflows/ |
ci.yml, release.yml, and pages.yml, which builds the website. See CI jobs and Releases and signing. |
.github/scripts/ |
The PowerShell scripts CI jobs run on fresh machines, the list of real apps they install, the stand-in for planted code, and build-site.py, which builds the website |
.cargo/config.toml |
The cargo quality and cargo typecheck aliases, and static linking of the C runtime |
rust-toolchain.toml |
Pins Rust 1.99.1, with clippy and rustfmt, for x86_64-pc-windows-msvc
|
deny.toml, about.toml, about.hbs
|
Dependency policy for cargo deny, and the template for THIRD-PARTY-LICENSES.md
|
Last changed 2026-11-11. Describes WinAppMigrator as of its latest release, 0.6.0.