Portable Linux Wine Launcher
  • JavaScript 89.9%
  • CSS 6%
  • HTML 2.6%
  • Shell 1.5%
Find a file
2026-10-05 17:37:23 +02:00
files/translations cleanup comments, update translations, bump to 0.4.1 2026-10-05 15:43:01 +02:00
node_modules add installer to build package 2026-09-25 20:38:23 +02:00
renderer improve small elements rendering, bump to 0.4.2 2026-10-05 17:37:23 +02:00
src cleanup comments, update translations, bump to 0.4.1 2026-10-05 15:43:01 +02:00
tools add support for directly launching windows exes from file exporer using .desktop shortcut 2026-09-30 17:32:30 +02:00
.gitignore add installer to build package 2026-09-25 20:38:23 +02:00
build.sh better installer and portable mode 2026-09-25 21:15:17 +02:00
development.md cleanup comments, update translations, bump to 0.4.1 2026-10-05 15:43:01 +02:00
package-lock.json add installer to build package 2026-09-25 20:38:23 +02:00
package.json improve small elements rendering, bump to 0.4.2 2026-10-05 17:37:23 +02:00
README.md code refactor & sync bugfixes 2026-10-05 13:43:49 +02:00
run.sh update icon & change PLGL to PLWL 2026-09-25 20:04:00 +02:00

PLWL — Portable Linux Wine Launcher

A portable launcher for Windows games and applications on Linux.

Portable layout

Everything the launcher needs lives next to the executable:

./files/
  wines/           imported Wine / Proton builds
  wineprefixes/    wine prefixes
  apps/            imported app folders (optional)
  data/            launcher config (apps.json, settings.json)
  translations/    translation files

Running

npm install
npm start

Building & installing

./build.sh produces build/PLWL-<version>.tar.gz: the Electron runtime renamed to olcxja.plwl/ (binary olcxja.plwl/olcxja.plwl, whole app in olcxja.plwl/resources/app.asar), plus the icon, install.sh and createshortcut.sh.

./install.sh               # install to ~/.local/bin/olcxja.plwl/ (icon + shortcut)
./createshortcut.sh        # portable mode: icon + shortcut only
./olcxja.plwl/olcxja.plwl  # or run without installing

Importing from a wine prefix

Besides copy/move/leave, an app can be imported from a prefix: nothing is copied — paths are stored relative to the prefix, so wine sees the app as installed on C:\ (registry entries keep working). Plain prefixes (drive_c on top) and Proton ones (pfx/) both work. The app stays tied to that prefix; removing the entry never deletes prefix files. A prefix can be renamed later — the folder moves and everything stored relative follows. Edits wait for running apps: renaming/deleting a prefix in use (or moving the default away from an app without its own) is refused with the app to close first; deleting a prefix that still has apps is refused too. Imports recreate symlinks (relative when the target belongs to the launcher) and keep permissions, so an imported game runs straight away.

"Open with PLWL"

The desktop entry registers .exe/.msi/.bat/.cmd/.lnk in file managers. Opening one shows a popup to pick the Wine/Proton build and prefix for that run (defaults preselected, nothing imported). A second instance hands the path to the running one. App shortcuts work as Open With targets too: the app receives the file as the Windows path it would get on Windows — C:\... inside its prefix, Z:\... otherwise. A file handed to an already running app goes to that instance instead of a second tracked run.

LAN syncing

Two PLWL installs on one LAN can mirror each other (sidebar → LAN syncing). No cloud, no accounts.

  • Device ID (24 chars) and Sync code (8 chars, letters+digits, case-insensitive), both re-rollable. A caller must prove it knows its own code; each verification costs 2 s and one may run at a time, so guessing is pointless. A correct code still opens an Accept/Decline popup on the receiver (60 s timeout); declining or ignoring never touches this machine and keeps the pairing.
  • Devices on your network are found over UDP and visible only while PLWL runs there (a few seconds after it closes they are gone).
  • Pick what to push: portable apps, prefix-imported apps, Wine/Proton builds, prefixes, Sync settings. Only what is ticked travels — without Sync settings the other machine's defaults and app configs are untouched. An accepted code is stored with the device ID, so later syncs need no typing; a re-rolled code is forgotten and asked for again.

Both machines show a progress popup (phase, unit, files, per-category counters like Apps: 2/5, transferred vs. planned bytes; the bar follows the current phase). The popups cannot be dismissed, and a sender hashing a big unit shows Waiting for the other device… instead of a dead popup — the sender pings while it works. They close on completion, or after 15 minutes of silence (and reopen if the sync turns out to be alive).

The sender is the source of truth: differing files are overwritten, missing ones written, extras inside the synced trees (files/apps/, files/wines/, files/wineprefixes/, files/data/icons/) deleted. Files are compared with BLAKE2b-512 (SHA-512/SHA-256 fallback); Force sync all files skips the comparison. Hashes are cached per file (size + mtime), so an unchanged library costs nothing to re-sync. Permissions travel with the files, and symlinks are sent as relative paths whenever the target belongs to the launcher (a Proton prefix's links into its build keep working on the other machine); dosdevices and targets outside files/ stay absolute, and links wine itself rewrote to absolute are relativized again on the wire, on import and before every run.

A sync also carries how apps are set up: wine build and prefix, args, env, DLL overrides, playtime and last played. Sync settings carries the registry-level part even when no files move: default wine/prefix, custom build names, prefix registry, every app's configuration and the library order. It only patches what already exists (unknown ids are ignored, unknown apps/prefixes stay), deletes nothing, and playtime only grows — the higher counter wins. Language, window settings, logs and external (leave) apps stay local.

Wine & Proton support

  • System Wine — wine from PATH.
  • Imported builds — drop any wine/Proton build into files/wines/ (one nesting level auto-detected). Symlinks are rewired to relative and executable bits restored, so builds from a zip or another machine run as they are. A build can get a display name of its own; the folder keeps its name.
  • Proton without Steam — invoked like Steam does it: STEAM_COMPAT_DATA_PATH linked to the launcher's prefix, STEAM_COMPAT_CLIENT_INSTALL_PATH pointing at a real Steam client when there is one (read-only) and at the empty files/data/fake-steam otherwise. GE builds run through Proton's UMU path (UMU_ID) with no Steam client at all. A per-app Disable UMU switch runs the build's own wine directly (runinprefix), as close to plain wine as it gets.
  • One C: drive per prefix — when a prefix has no pfx yet, PLWL makes pfx a relative symlink back to the prefix itself, so Proton and wine share one drive_c, registry and dosdevices. Existing layouts (a real pfx/ folder, a prefix with both trees) are left exactly as they are.

Translations

All UI text comes from JSON files in files/translations/: data holds the language names, texts maps keys to strings with {0}, {1} ... placeholders. The bundled files are refreshed into that folder on every start when their content changed (so updates deliver new keys); user-added languages are never touched.

Development

Codebase overview and contributor rules: development.md.