WPT is a Linux-side manager for supported Neural DSP Windows plugins. It installs, inventories, repairs and removes plugin files in an ableton-linux Wine prefix, and can launch installed standalone apps.
Developed on CachyOS with the ableton-linux stack. The GUI can save and switch between Wine and prefix profiles. Set up PipeASIO separately through ableton-linux; WPT does not configure audio routing. The 0.6.5 file-manifest, install-plan and uninstall paths have synthetic-prefix tests only. The profile-based standalone launcher has fake-Wine tests only. Neither has live-prefix validation. See verification limits.
- Install
- Requirements
- What it does
- Why this exists
- Coming from Windows
- Command line
- GUI
- How it verifies
- Scope and limitations
- Development
- Credits
- AI Disclosure
Choose your distro below. The release includes a ready-to-install package for Arch-based systems. Other distributions install from the verified source archive in an isolated Python environment.
These commands install WPT. wpt doctor reports missing system tools but does not install them.
The Arch updater can install a WPT update with pacman when you choose it.
Before using WPT, set up the ableton-linux Wine prefix and staged Wine tree. Configure PipeASIO
separately if you need audio. Back up the prefix before install, repair or uninstall operations.
These steps do not install Neural DSP plugins or Wine.
Arch / CachyOS (recommended)
-
Download the
wine-plugin-toolkitpackage and matching.sha256file from the latest release. -
In the download folder, verify and install the exact package you downloaded. Replace the version and package revision below if the release is newer:
cd ~/Downloads VERSION=0.6.5 PKGREL=1 PACKAGE="wine-plugin-toolkit-${VERSION}-${PKGREL}-any.pkg.tar.zst" sha256sum -c "${PACKAGE}.sha256" sudo pacman -U "$PACKAGE"
Pacman installs the required Python and
msitoolsdependencies. For the GUI, also install the optionalpyside6package withsudo pacman -S pyside6. -
Run
wpt doctor. Launch the window withwpt-gui.
Build the Arch package from source instead
Install base-devel, then download the source archive and checksum from the release page. Verify
and extract the exact archive before building:
sudo pacman -S base-devel
cd ~/Downloads
VERSION=0.6.5
SOURCE_TARBALL="wpt-${VERSION}.tar.gz"
sha256sum -c "${SOURCE_TARBALL}.sha256"
tar xzf "$SOURCE_TARBALL"
cd "wine-plugin-toolkit-${VERSION}"
SRCDEST="$HOME/Downloads" makepkg -siDebian / Ubuntu and derivatives
-
Install the system requirements. WPT needs Python 3.11 or newer; some older distro releases ship an older default, so check the version first.
python3 --version sudo apt install python3 python3-venv msitools
If the distro's
python3is older than 3.11, install a supported Python version and its matching venv package. In step 3, use that interpreter in place ofpython3(for example,python3.11). -
Download the
wpt-<version>.tar.gzarchive and matching checksum from the latest release, then verify and extract it. Replace0.6.5with the release version you downloaded.cd ~/Downloads VERSION=0.6.5 SOURCE_TARBALL="wpt-${VERSION}.tar.gz" sha256sum -c "${SOURCE_TARBALL}.sha256" tar xzf "$SOURCE_TARBALL" cd "wine-plugin-toolkit-${VERSION}"
-
Install into a stable virtual environment and check the setup. The command includes the GUI extra.
python3 -m venv "$HOME/.local/share/wpt/venv" # create once, reuse for updates "$HOME/.local/share/wpt/venv/bin/python" -m pip install --upgrade '.[gui]' "$HOME/.local/share/wpt/venv/bin/wpt" doctor
For CLI-only use, replace
'.[gui]'with.in the install command. To open the GUI:"$HOME/.local/share/wpt/venv/bin/wpt-gui"
Fedora
-
Install the system requirements. WPT needs Python 3.11 or newer.
python3 --version sudo dnf install python3 python3-pip msitools
-
Download the
wpt-<version>.tar.gzarchive and matching checksum from the latest release, then verify and extract it. Replace0.6.5with the release version you downloaded.cd ~/Downloads VERSION=0.6.5 SOURCE_TARBALL="wpt-${VERSION}.tar.gz" sha256sum -c "${SOURCE_TARBALL}.sha256" tar xzf "$SOURCE_TARBALL" cd "wine-plugin-toolkit-${VERSION}"
-
Install into a stable virtual environment and check the setup. The command includes the GUI extra.
python3 -m venv "$HOME/.local/share/wpt/venv" # create once, reuse for updates "$HOME/.local/share/wpt/venv/bin/python" -m pip install --upgrade '.[gui]' "$HOME/.local/share/wpt/venv/bin/wpt" doctor
For CLI-only use, replace
'.[gui]'with.in the install command. To open the GUI:"$HOME/.local/share/wpt/venv/bin/wpt-gui"
Other Linux distributions
Install Python 3.11 or newer, its venv support, and msitools using your distro's package
manager. Then follow the source-install steps above. GUI installs use the .[gui] extra; the
optional wrapper unpackers may improve support for wrapped installers; package names vary by distro.
For later terminal sessions, activate the source-installed environment before using the commands below:
. "$HOME/.local/share/wpt/venv/bin/activate"To remove a source install, remove only its venv directory. The sibling presets directory may
contain rescued user data.
- Linux x86-64 and Python 3.11 or newer. On Debian/Ubuntu, check
python3 --versionbecause the distro default may not meet this requirement. msitoolsfor reading and unpacking MSI packages.- A prepared ableton-linux Wine prefix with
drive_c(default~/.wine-ableton), plus a staged tree under~/.local/opt/wine-d2d1-nspa-<version>containingbin/wine. - PySide6 is optional and needed only for the GUI. Source installs include it with the
.[gui]extra. - The GUI can save and switch between profiles that select a Wine tree and prefix. WPT does not bundle
the Wine runtime, install or configure PipeASIO, select audio devices or route audio. Configure
PipeASIO through ableton-linux before expecting audio.
Run in Standalone, installer fallbacks that require Windows code, a registered uninstall, and registry removal with--purgeneed the selected tree's workingbin/wine. MSI metadata and supported file operations can usemsitoolswithout launching Wine. WPT selects the newest matching staged tree and does not promise every Wine build or patch set works with every plugin.
For non-default paths, set WINEPREFIX or pass the global --prefix and --tree options before
the subcommand. --home is a discovery override, not a general HOME override; it changes the
home used for Wine-tree/product discovery and the rescue-store check in wpt doctor. It does not change the Wine prefix or redirect the
preset store used by presets and uninstall, update
cache/config or Downloads search. Those use the current $HOME/XDG locations. When --home
differs from $HOME, doctor may inspect a different rescue store from the one uninstall writes to.
After installation, start with:
wpt doctor
wpt env
wpt listdoctor reports missing tools and the suggested fix. To point it at a non-default stack, put the
global options before the subcommand. Replace 11.13 with your installed tree version:
wpt --prefix "$HOME/.wine-ableton" --tree "$HOME/.local/opt/wine-d2d1-nspa-11.13" doctorSource installs are separate from the Arch package. wpt update updates Arch packages only; update
a source install by installing the newer source release into its virtual environment.
- Installs a plugin from the vendor's MSI, or from the vendor's
.exeinstaller, by unpacking it withmsitoolsand placing the payload itself. - Checks each selected MSI
Filerow at its full destination path, including bundle internals, against its declared byte size. This is not a content-hash or component-state audit (see verification limits). - Attempts repair of missing or wrong-sized File-table files from a cached MSI; preset no-clobber rules can leave a mismatch unresolved, and a same-size edit is not detectable.
- Uninstalls stage/read the MSI before the default registered removal route. That route attempts
preset rescue before Wine's
msiexec /x. A failed rescue stops the job whenever rescue is required by the selected route. The toolkit's direct remover preserves modified files, no-clobber files, known cross-product paths, and files whose MSI component state is uncertain. Registered uninstalls stop before vendor removal when the payload is unavailable, the cached-MSI ownership scan is incomplete, or another cached product claims a planned path.--files-onlyskips Wine on the CLI. Wine's vendor uninstall can still remove other files; back up your data (see uninstall limits). - Inventories what is installed, and finds installs that registered but never copied their files.
- Hides and restores a plugin from your DAW's scanner with a reversible rename.
- Attempts Linux extraction first for recognised 7-Zip, Inno, InstallShield, NSIS, Burn and CAB wrapper families when the corresponding unpacker is installed. This is not a promise that every vendor installer works without Wine; Advanced Installer (including Neural DSP) needs Wine.
Some vendor MSIs assume Windows behavior Wine does not provide on these paths:
- a bootstrapper-only launch condition, like
SETUPEXEDIR OR (REMOVE="ALL"), somsiexec /icannot succeed (error 1603); - JScript custom actions built on
Scripting.FileSystemObjectandWScript.Shell: Wine's stubs answerObject doesn't support this action, the install copies nothing (error 103) and still registers the product as installed; - an invisible maintenance dialog on some upgrade paths, which Wine may not paint, leaving the installer waiting until the process is stopped.
For supported packages, msitools can read and unpack the MSI on Linux. This tool uses that route to
place selected payload files and check them afterwards; package-specific behavior still needs
validation. The case that started it: an Archetype plugin upgrade where the wrapper hung at
"Starting install" with an empty progress bar, msiexec failed twice, and the prefix claimed the
product was installed while not one plugin file existed on disk.
Licensing and files. Removing plugin files does not free or transfer an iLok activation; handle activation separately through the vendor or iLok. WPT writes plugin files inside the prefix and may also use scratch space, preset-rescue storage and exports outside it. Wine's own uninstall can affect host paths mapped into the prefix, so back up important data first.
What you need first. Prepare the prefix and staged Wine tree using the ableton-linux project. WPT works with that configured stack; it does not replace the runtime setup or guarantee every vendor installer will work. For supported packages, WPT can extract and verify MSI payloads on Linux. Installers that require Windows code run through the selected Wine tree.
Your plugin installers. Move the .exe and .msi files you downloaded on Windows into
~/Downloads on Linux (a USB stick or your network drive is fine). Then:
wpt pending # what installers are sitting there, and are they installed already
wpt install ~/Downloads/ArchetypeNollyXv1.0.2.exepending guesses the product and version from the file name, and says whether that version is already
in the prefix. install reads the installer and shows planned destinations (a directory may contain
more files than the preview lists) before writing them. It refuses to create a second destination
whose spelling differs only by case. Add --dry-run to preview prefix writes without placing plugin
files; staging/extraction can still write to scratch.
Your own presets, sounds and MIDI maps. These are the one thing a reinstall cycle cannot bring
back. Copy them off the Windows machine (usually Documents\Neural DSP\..., or wherever you saved
your own sounds) into the prefix, or keep them somewhere safe on this machine, then:
wpt presets # what is in the prefix now
wpt presets --export ~/Documents/my-presets # copy it all out to a plain folderFactory and artist presets come back with a reinstall. Yours do not, so back them up before you
uninstall anything. wpt uninstall rescues recognised presets and attempts to copy regular files it
can enumerate under planned no-clobber paths before Wine; a detected symlink or failed copy stops
removal. When WPT has a readable File-table plan, the CLI and GUI refuse an uninstall before rescue or
msiexec if a planned prefix path is symlinked or case-insensitively ambiguous. WPT cannot prove that every user file was discovered; Wine may delete originals, and other personal files may not be identified. Keep your own backup. --no-rescue skips the CLI backup; --files-only avoids
msiexec on the CLI. --no-files skips the plan/preflight and still delegates to Wine, so its file
effects are not bounded by WPT.
Activation and iLok. Some vendors use iLok (PACE) or an account-based licence. The toolkit does not touch licensing, and deleting plugin files never returns a licence slot. If a plugin was activated on a prefix you are retiring, deactivate it in iLok License Manager first. If that location is already broken or unreachable, use Report as Unusable there so the slot comes back. This trips people up, so it is repeated in the uninstall warning.
Things that will not work here.
- Drivers. Some downloads are drivers or helper applications, not plugins: Neural DSP's Nano Cortex package is a Windows USB driver plus a control panel. Those are refused by default, with the reason and the folder their files wanted. Placing a driver's files by hand does not install it because drivers need their INF and service registration.
- Linux-native plugins. This manages Windows plugins inside a Wine prefix. A Linux VST3 or CLAP belongs in your normal Linux plugin directories and has nothing to do with this.
- macOS and Windows prefixes. Out of scope.
All of it is one CLI. Every command has --help, and list and pending take --json when you want
to paste machine-readable state into a bug report.
wpt doctor # check everything it needs, and say what is wrong
wpt env # tree, prefix, Windows user, every plugin directory
wpt list # inventory: what is installed, and is each file intact
wpt scan # installs that registered but never copied their files
wpt products # triage every product in every Wine prefix on this machine
wpt pending # installers downloaded but not installed yet
wpt find-msi # vendor MSIs already unpacked inside the prefix
wpt inspect <msi> # identity, install targets, launch conditions, payload
wpt plan <msi> # extract and show planned destinations
wpt install <msi> --dry-run # preview prefix writes; extraction still uses scratch
wpt install <msi> # do it, then run the current (limited) size checks
wpt install ~/Downloads/VendorSetup.exe # or point it straight at the vendor's .exe
wpt repair --product Rabea # attempt to re-place missing/detected wrong-sized files
wpt disable Nolly # hide a plugin from the DAW scanner (a plain rename)
wpt enable Nolly # bring it back
wpt uninstall --product X # see the uninstall limits below before running for real
wpt wrappers # identify every .exe installer around, and its route to an MSI
wpt presets # your presets and downloaded packs, and what has been rescuedlist and scan are complementary. list walks the plugin directories and answers "what is there".
scan walks the prefix registry and answers "what do the installers claim is there". A plugin in
neither is not installed. A plugin that shows in scan but not list is the failure this tool was
written for: registered, with the files missing.
Useful options. Global flags must come before the subcommand (for example, wpt --prefix PREFIX --tree TREE list); operation flags follow the command:
| flag | why |
|---|---|
--product <substring> |
pick an MSI from the prefix without typing the path (--product Rabea) |
--dry-run |
preview planned destinations without applying prefix changes; MSI staging/extraction still writes to scratch. A directory is one row even if it contains other files; external Wine effects are not predicted. |
--no-vst2 / --no-standalone / --no-presets |
skip parts you do not want |
--aax |
include the AAX plugin (Pro Tools only, off by default) |
--scratch <dir> |
where the payload is extracted (default /tmp/wpt-extract) |
--home <dir>, --prefix <dir>, --tree <dir>, --user <name> |
global: set discovery home, Wine prefix/tree or Windows user; place before the subcommand. See the home-scope note above. |
--json |
machine-readable output, for a bug report |
Most CLI exit codes: 0 ok · 1 verification, scan or system error · 2 bad input ·
3 environment not found · 4 msitools error, external-tool timeout or uninstall preflight
read/safety failure · 5 catalogue error · 130 interrupted.
For uninstall, 1 includes rescue, msiexec (including timeout), post-msiexec verification, file
removal or registry purge failures; unexpected system errors also return 1. Missing MSI or
ProductCode input is 2. 4 covers an MSI/plan preflight read failure or safety refusal.
wpt doctor uses 0/1/2 for clean/warning/failure, as described below.
Vendors ship a .exe whose real payload is an MSI, which is all this tool can read. wpt install
takes either, and gets from one to the other by the cheapest route that works:
- it is already an MSI: use it;
- the wrapper has been run before, so its MSI is already cached in the prefix: use that, run nothing;
- an unpacker that suits the wrapper's format can pull an MSI out of it: done, no Wine;
- otherwise it runs the vendor installer under Wine once (
--run-wrapper, or the GUI asks first) and picks up the MSI that lands in the prefix.
The wrapper's format decides which tool is tried, and saying what a file is comes before spending minutes on it:
wpt wrappers # every .exe installer around, and its route
wpt wrappers --file ~/Downloads/X.exe # one file in detail
wpt wrappers --file ~/Downloads/X.exe --unpack # actually unpack it and report| family | how it is recognised | route |
|---|---|---|
| Advanced Installer (LZMA) | Caphyon / Advanced Installer |
Wine only: no Linux tool reads it |
| NSIS | \xEF\xBE\xAD\xDE at offset 0 |
7z, then cabextract |
| Inno Setup | Inno Setup Setup Data, JR.Inno.Setup |
innoextract, then 7z |
| InstallShield | InstallShield, setup.inx, data1.cab |
unshield, 7z, cabextract |
| WiX Burn bundle | WixBundle / wixburn |
7z, then cabextract (the payload is an appended cabinet) |
| 7-Zip self-extractor | the 7z signature |
7z |
| IExpress / CAB self-extractor | IExpress, MSCF |
cabextract, then 7z |
| anything unrecognised | nothing matches | every installed unpacker, in turn |
Two details that make this work on real files rather than tidy ones:
- containers are found by content, not by name. A Burn bundle hands its payload over as members
called
a0toa13, and a self-extractor as[0], so*.caband*.msiare not the search: the cabinet magic (MSCF) and the MSI magic (an OLE compound document) are. Verified onvc_redist.x64.exe, whosea10is read by msitools as Microsoft Visual C++ 2022 X64 Additional Runtime. - architecture is chosen deliberately. Wrappers that carry every architecture (
arm64/,x86/,x64/, same file name inside each) default to x64, and a wrapper named...-win-x86never resolves to the bigger x64 MSI just because it is bigger. Where a wrapper holds several MSIs, the one used is named and the rest are reported.
Neural DSP wrappers are Advanced Installer packages whose payload is an AI LZMA stream, which no Linux
tool can unpack (7z lists the PE and hands you a blob it cannot open). For those the Wine step is
what actually works, and the tool says so instead of leaving you guessing: a wrapper identified as that
family is refused immediately, with the reason.
Not every vendor download is a plugin. Drivers and helper applications are refused by default, with the reason and the destination their files wanted:
wpt install "~/Downloads/NeuralDSP Nano Cortex v5.74.0.exe"
nothing a DAW can use: this package is an application or a driver, not a plugin.
PFiles64 payload would go to .../Program Files/NeuralDSP/NeuralDSP Nano Cortex Driver v5.74.0
Its own installer (or the vendor's .exe under Wine) is what installs it
properly - drivers need their INF and service registration, which placing
files by hand does not do. Pass --include-app-files to place them anyway.
Pass --include-app-files to have those placed anyway (subject to the size-check limits above), knowing
no DAW will see them. A plugin package is unaffected by this rule: its own standalone app is still
installed.
wpt catalogue # every plugin they ship, current version, where it lives
wpt catalogue --open-page # open their full downloads list, every plugin's page in one view
wpt catalogue --refresh # re-read their page (otherwise a bundled snapshot is used)
wpt catalogue --open nolly # open one plugin's download page in your browser
wpt catalogue --download "Cortex Control" # public CDN links only (hardware and manuals)Why it opens a page instead of downloading for you: the plugin links are behind a sign-in and are
licence-bound, so nothing outside your browser can fetch them. The hardware and manual links are
public, and --download does fetch those.
wpt presets # yours, the packs, and what has been rescued
wpt presets --export ~/Documents/my-presets # copy them all out to a plain folder
wpt presets --sources # where to get more: repositories, vaults, shops
wpt presets --open "Preset Junkie" --product "Nolly X"Presets and user files may not be recoverable after an install or uninstall. Back them up first.
Factory and artist presets usually come back with a reinstall. Your own (<product>/User/*.xml),
downloaded packs (<vendor>/<vendor>/<Pack> Presets/) and hand-made MIDI maps may not. The toolkit attempts to copy
presets it recognises to ~/.local/share/wpt/presets/<product>/<timestamp>/ before both Wine's
msiexec /x and its own file deletion, without overwriting an existing rescue. A failed rescue
copy stops the job. The GUI has no --files-only equivalent. The toolkit now leaves files outside
the exact File-table manifest in place, but Wine's msiexec /x can still remove them. Back up your
files before uninstalling. --no-rescue skips the toolkit's rescue; it is not a safety option.
The toolkit does not fetch presets from the internet, deliberately: the community repositories want a sign-in, one vault sits behind a bot filter, and the shops want money. What it does is open the right page in your browser, pre-filled with the plugin you are looking at. Where a site's search URL could not be verified, no search parameter is invented: you get the front page.
wpt update # query the latest release live; add --cached to reuse a saved result
wpt update --install # download it, verify it, then print the pacman line
wpt update --install run # ...and open a terminal to install it, then reopen the appThe GUI checks quietly at startup, keeps the answer for a day, and puts Check for updates in its
toolbar. Installing always happens in a visible terminal running sudo pacman -U, which means the app
closes first so pacman can replace its own files, then reopens when the install finishes. It never
escalates privileges on its own. Downloads are checked against the release's published sha256 when
there is one, and refused unless the file really is a pacman package. WPT_NO_UPDATE_CHECK=1 turns
the startup check off, and "Skip this version" silences one release.
wpt doctor # tree, prefix, permissions, tools, cached MSIs, inventory, GUI
wpt doctor --json # the same, machine-readable: paste this into a bug reportIt checks the things that actually break this kind of tool: a Wine tree that is not the staged one,
msitools missing, a plugin directory that is not writable, no cached MSI to verify sizes against, a
scratch directory it cannot write to, PySide6 absent. Each check says what to do about it, and the
exit code is usable from a script: 2 for something that must be fixed, 1 for optional things
missing, 0 for clean.
| symptom | what it usually means |
|---|---|
env cannot find a Wine tree |
no staged ~/.local/opt/wine-d2d1-nspa-*, or yours is elsewhere: pass --tree |
a plugin reads unverified |
the MSI for it is not cached in the prefix, so there is no size to compare. Repair and uninstall need that MSI |
the vendor .exe hangs at "Starting install" |
expected for Advanced Installer wrappers: it is a Wine limitation, and wpt wrappers --file X.exe will say so before you spend the time |
| an install reports 0 destinations | the package is an application or a driver, not a plugin. The log says which |
| the GUI will not start | pyside6 is not installed (wpt doctor says so), or you are on a headless session |
| a plugin vanished from your DAW | check the Plugins tab for a disabled state, or wpt list: disable is a rename, and wpt enable undoes it |
wpt completions fish > ~/.config/fish/completions/wpt.fish
wpt completions bash | sudo tee /usr/share/bash-completion/completions/wpt
wpt completions zsh | sudo tee /usr/share/zsh/site-functions/_wptGenerated from the real argument parser, so they cannot drift as commands are added. The Arch package installs all three.
wpt-guiSix tabs, in the order you use them, each a thin wrapper over the same core functions as the CLI:
- Environment: choose Auto-detected or a saved launch profile. Manage profiles… stores a
profile name, Wine prefix, custom Wine tree and literal
NAME=VALUEenvironment overrides. The selected prefix/tree are used by WPT operations and Run in Standalone, so inventory and launch stay on the same prefix; environment overrides are passed only to Run in Standalone, not to installs, repairs or uninstalls. They are literal environment variables only: WPT does not load or modify a PipeASIO config file or audio routing. Changing prefix/tree clears prefix-derived lists and reports; refresh those views before acting. Profiles live in~/.config/wpt/launch_profiles.json(or$XDG_CONFIG_HOME/wpt/launch_profiles.json), with mode0600; values are plain text, so do not store passwords or tokens. Overrides are literal, not shell commands, and cannot replace Wine's selected prefix/runtime or its user identity. Already-open WPT windows keep their current stack until Re-detect; stale profile writes are refused. Removing the active profile falls back to Auto-detected with a warning. The Environment tab also shows the active tree, prefix, Windows user and plugin directories, and warns if msitools is missing. - Plugins: the inventory. Kind, size, and an integrity verdict against the cached MSI (
ok,unverified,BROKEN), plus a State column for disabled plugins. The buttons act on the selected row: Repair selected from cached MSI, Disable (hide from DAW) or Enable, Uninstall. Right-click a row for the same actions plus the file's path, preset sites, Browse local files and (when one exact-name.exeexists under this prefix's Program Files) Run in Standalone through the selected profile's custom Wine tree and environment. Unverified MSI ownership is marked in the action; the app may contact its licensing service.Program Files (x86)is not searched. Standalone apps run under the selected Wine profile. WPT does not install or configure PipeASIO, select audio devices or manage routing; configure the audio stack separately through ableton-linux. Within one WPT window, multiple apps can be launched under its active profile; tracked groups block profile changes, prefix writes and update restarts while active. WPT starts each launcher in a separate session and does not signal it when the window closes. Vendor apps may impose their own concurrency limits. Closing with active groups requires Close WPT; don't stop apps; the default and Escape keep WPT open. Closing ends that window's tracking; reopened or separate WPT windows do not rediscover earlier launches. Close those apps, detached helpers and licensing services before using WPT to modify the prefix. - Download: Neural DSP's catalogue, with version, release date, whether it is installed here and
whether an installer is already in
~/Downloads. Download Selected Plugin opens its page in your browser; the Preset & IR sources row opens preset sites for the plugin you have selected. - Pending Install: installers sitting in
~/Downloadsor the prefix root that are not installed yet, or are an upgrade. Install selected runs the same extract, place and size checks as the CLI, one plugin at a time. This is the staging step: download on the previous tab, install on this one. - Install MSI: pick or browse an MSI, choose VST3 / VST2 / standalone / presets, Preview plan then Install. A results table and a log show the current, limited size checks.
- Diagnostics: scans the prefix registry for plugin paths that do not exist on disk, lists the products it registers (runtimes hidden), and Triage products in every Wine prefix reports what every prefix on the machine holds and which entries are debris.
Long operations are dispatched to worker threads; this is not a guarantee that no GUI path can block.
A disabled plugin stays visible, flagged disabled, so it can be brought back.
The toolkit does not take an installer's exit status as proof of correct file placement. In this version it checks selected File-table paths, but size is not a content hash:
- the plan maps Directory/Component/File rows to full destination paths. Payload builds reject a missing, extra or wrong-sized extracted file before copying; tables-only plans cannot install;
verify_plancompares each selected File-table file's size, including bundle internals and zero-byte files. Two different rows with one case-insensitive destination are refused;BROKENinlistis a size mismatch at a full path;unverifiedmeans there is no unique mapped MSI owner;okmeans that one file's size agrees with its MSI row. It cannot prove its bytes are unchanged or that every optional MSI component was installed;- state is cross-checked two ways: the plugin directories (
list) and the prefix registry (scan); - GUI Run in Standalone requires one exact-name, non-symlink
.exeunder the active profile's Program Files;Program Files (x86)is not searched. It uses the selected profile's Wine tree, prefix and standalone-only environment overrides, and refuses a verified executable if its size changed since inventory (refresh to retry). Logs go to absolute$XDG_CACHE_HOME/wpt/standalone/; if it is unset or non-absolute, WPT falls back to~/.cache/wpt/standalone/. Logs are retained, not auto-pruned.wpt/standalone.pyusesstart_new_session=True. The GUI test checks two synthetic fake-Wine child process groups survive WPT close;standalone_process_detach_check.pychecks a child survives its launcher interpreter exiting. Neither test exercises real Wine, vendor software, licensing or services. Size agreement is not a content hash; wpt doctorchecks the surrounding environment. GUI suites exercise tabs offscreen on a machine with PySide6; they do not replace real-desktop checks.
The remaining real-MSI, feature-state and release-artifact acceptance criteria are in
the claim ledger and the design review map. Do not interpret
an ok result as a complete MSI payload audit.
- Earlier 0.6.4 work exercised Neural DSP installers (Advanced Installer and MSI) against a real Wine prefix. That is historical evidence, not a real-install or live-uninstall validation of the manifest/uninstall changes in 0.6.5. This version has read-only table/listing comparisons and disposable-prefix tests; no real prefix has been modified to test those changes.
- Wrapper families: the recorded real-wrapper examples cover a 7-Zip self-extractor (a Neural
DSP hardware wrapper), WiX Burn bundles (
vc_redistanddotnet-runtime) and Advanced Installer (refused as Wine-only). The other named families are code paths, not a claim that a real installer of each family has passed. Known gap:innoextracton a current Arch is older than the newest Inno Setup releases, so a brand-new Inno installer is identified but not opened. The tool says which version it could not read rather than pretending. unshieldis used for InstallShield if it is installed, but it is not part of the base install. Without it, InstallShield wrappers fall through to7zandcabextract, and then to Wine.- Only files a plugin MSI describes count as plugins. Wine's own tools (
iexplore.exe,wordpad.exe,wmplayer.exe) and other vendors' helpers (Bonjour, iLok) sit in the same directories and are not. They are counted in one line oflistoutput, and shown on request with--all-standalone(the GUI has a show other .exe files box). Same rule for the MSI picker. scan's list of present paths can include a plugin's support dlls (Qt'sqwindows.dlland friends live in plugin directories and are legitimate entries). They are not noise to filter blindly, just more entries than the four paths you may be looking for.uninstallreads the MSI before it runsmsiexec /x. Windows Installer can delete its cached MSI during removal, and that cache may be the only copy the toolkit can find. The ProductCode and plan are read first, and the MSI is staged out of reach. If it cannot be read, the toolkit stops before prefix removal; scratch staging may already have written temporary files. Once msiexec removes the registration and the cache, no MSI may be left to describe the product:wpt uninstall --product Xthen says so and lists what the prefix still holds under that name, rather than pretending.- Uninstall boundaries. For a registered product, WPT runs
msiexec /xonly after reading the MSI and passing its payload and cached-owner checks. It refuses the default registered uninstall before vendor removal if payload bytes are unavailable, the selected MSI has an unmapped root, any cached-MSI ownership map is unreadable/unmapped, or another product claims a planned path. Unsafe fallback Manufacturer/ProductName path components also refuse planning. This broad fail-closed scan may block removal because of an unrelated cached MSI. If no product is registered, the CLI and GUI skipmsiexec. A non-zeromsiexecresult, or a zero exit while registration remains or cannot be read, stops subsequent direct file removal and registry purge. In file-only/unregistered cleanup, WPT compares eligible files with the exact MSI payload bytes and declared size, and preserves modified, no-clobber, shared, and component-state-uncertain files as leftovers. It prunes empty parents, not entire directories. Install plans also refuse optional, conditioned, source-only, shared-reference, permanent, transitive,Sharedor NeverOverwrite components because component-selection state is unavailable. FeatureComponents/feature-level selection is not modelled. Repair and inventory still use size checks, so same-size edits can remain undetected there. Preset rescue happens beforemsiexec; WPT uses the selected MSI's Manufacturer when locating its ProgramData tree and strictly attempts to copy regular files under planned no-clobber paths and recognized Roaming/MIDI XML paths. Existing no-clobber files without a successful rescue result, traversal/stat errors, detected symlinks, unsupported file types or copy failures stop the job. Roaming/MIDI XML maps are strictly traversed under inferred paths, but product-name lookup and uninspected custom actions do not prove complete discovery; this is not a complete backup guarantee. Wine may still affect other user files or host-mapped paths (such as Desktop). Back up user data and inspect--dry-run; the GUI has no--files-onlyroute. On the CLI,--files-onlyskips Wine's registration removal and preserves refused paths.--no-filesskips WPT's plan, removal, and rescue, but Wine can still delete files; it also skips shared-file ownership checks, somsiexec /xmay remove files another product claims.--no-rescuealso bypasses the CLI backup.--purgeis gated on successful vendor uninstall and the absence of remaining mapped MSI files; a matching basename or product name alone is not proof.--dry-runlists mapped files and known refusals, not every external Wine effect; staging/extraction may still write to scratch. Purging never frees an activation. - Which MSIs the tool can see. Sizes are cross-checked against the MSIs cached inside the prefix: a
vendor's own folder (
AppData/Roaming/Neural DSP/...),ProgramData/Package Cache, and Wine's Windows Installer cache (drive_c/windows/Installer/). That last one matters, because a product installed by running its vendor wrapper may only leave its MSI there, and without finding it the plugin readsunverifiedand has nothing to repair or uninstall from. Routine inventory takes only MSIs that declare a plugin payload directory (VST3DIR/VSTDIR/AAXDIR/APPDIR/PREDIR) from that cache, so runtime MSIs do not slow the listing or appear as plugins. The destructive ownership check also considers non-plugin cached MSIs and mapped application/driver roots, because they may own shared files. An unreadable or unmapped cache record stops a registered uninstall; this conservative scan may be slower and may require manual cache repair. MSIs outside the searched cache locations are not proven absent owners. - The GUI runs one background job at a time. A running job keeps its reference until it finishes, a
second request is declined with a line in the log rather than queued, and closing the window waits for
a running job. Each of those is a crash that was hit for real: Qt aborts the process, with no
exception and no traceback, when a
QThreadthat is still running loses its last reference. --scratch(where the MSI is unpacked, default/tmp/wpt-extract) is emptied before each extraction, because a plan is built by listing the extracted folders: stale payload from another product would otherwise be copied into the prefix on install, or deleted from it on uninstall. A scratch path that is not empty, was not created by wpt (no.wpt-extractmarker) and sits outside the temp dir or~/.cacheis refused rather than wiped.- iLok is diagnosed, not automated:
scantells you a plugin is missing files, but licence slots are still checked by hand at https://www.ilok.com, under My Licenses. - macOS, Windows, and prefixes that are not the ableton-linux shape are out of scope.
python3 tests/test_core.py # pure logic, no prefix needed
python3 tests/test_prefix_integration.py # builds a synthetic prefix and exercises everything
QT_QPA_PLATFORM=offscreen python3 tests/gui_smoke.py # builds the GUI and runs every tab
QT_QPA_PLATFORM=offscreen python3 tests/gui_buttons_check.py # clicks every button offscreen
python3 tests/readme_claims_check.py # parser/tabs/flags/known limitations (not real-MSI proof)The full runner isolates TMPDIR only. Use disposable HOME, XDG paths and WINEPREFIX as described
in TESTING.md; never point the full or GUI suite at a live prefix.
test_core.py covers Wine tree version ordering, .reg value decoding (including UTF-16 str(2)
blobs), Windows to Linux path mapping, plugin-path classification, destination resolution from MSI
directory properties, and the CLI surface. test_prefix_integration.py builds a fake ~/.wine-ableton
with a fake tree, plugin folders and a registry that mixes present and missing paths, then checks
detection, the inventory, the diagnostics scan, the repair filter and plan application against each
other. Neither needs msitools, a real installer or a real prefix.
wpt/environment.py locate tree, prefix, user, directories; build the launcher environment
wpt/msi.py msitools wrappers: identity, LaunchCondition, File table, msiextract
wpt/installer.py build a copy plan, apply it, verify sizes, repair filter, uninstall, enable/disable
wpt/inventory.py what is installed: walk plugin directories, cross-check sizes against cached MSIs
wpt/installers.py what is not installed yet: installer discovery, name and version parsing
wpt/products.py triage: every prefix walked, product records read, verdicts against the disk
wpt/presets.py your presets and downloaded packs: list, export, rescue before removal
wpt/scan.py registry against disk diagnostics, registration lookups for uninstall and purge
wpt/cli.py argparse front end (every real behaviour lives in the modules above)
wpt/gui.py PySide6 front end (no logic of its own)
packaging/ launchers, PKGBUILD helpers, desktop entry, icons
tests/ the suites listed above, plus wrapper corpus and GUI layout checks
One design rule holds the whole thing together: no logic in the front ends. If the GUI and the CLI could ever disagree, the bug belongs in a core module.
Before submitting a behaviour claim or code change, see CONTRIBUTING.md and the claim ledger. A code citation is not proof of a real-machine result.
- msitools reads and unpacks the vendor MSIs.
- shibco/ableton-linux is the Wine stack and prefix this target shape comes from.
7z,cabextract,innoextractandunshieldunpack the wrapper families listed above.- Not affiliated with Ableton, Neural DSP, or any plugin vendor. Plugin names appear only to say what was tested.
MIT licensed. See LICENSE and CHANGELOG.md.
Development here is AI-assisted. An agent (Hermes, by Nous Research) uses models through OpenRouter, which can vary by task. The agent helps with diagnosis, reproduction, implementation, test authoring, documentation and release tooling. The maintainer owns release decisions.
The release gate for future changes requires a reproduced defect, a regression check, the full suite from an extracted release tarball, an independent review, and checksum comparison of published artefacts against what was built. The published 0.6.4 release predates the claim ledger; version 0.6.5 retains the verification and uninstall limitations stated above. A passing script alone does not certify every README sentence; see the claim ledger for what is still open.
Contributions: AI-assisted work is welcome if you understand it and can explain the change, and if it comes with evidence: a reproduction, a test, or a reason. We will not accept fully-vibecoded contributions, where nobody can account for the code, because the risk of regression is too high.
