- JavaScript 89.9%
- CSS 6%
- HTML 2.6%
- Shell 1.5%
| files/translations | ||
| node_modules | ||
| renderer | ||
| src | ||
| tools | ||
| .gitignore | ||
| build.sh | ||
| development.md | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| run.sh | ||
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) with the whole app (code, renderer and bundled files/) packed into olcxja.plwl/resources/app.asar, plus the olcxja.plwl.png icon, install.sh and createshortcut.sh:
tar -xzf PLWL-<version>.tar.gz
cd PLWL
./install.sh # copies everything to ~/.local/bin/olcxja.plwl/,
# installs the icon (olcxja.plwl.png) + shortcut
# removes the extraction folder, launches
./createshortcut.sh # portable mode: only installs the icon + shortcut
# or run without any shortcuts:
./olcxja.plwl/olcxja.plwl
Importing from a wine prefix
Besides copy/move/leave, an app can be imported from a wine prefix: pick the prefix, then the app folder inside its drive_c. Nothing is copied — paths are stored relative to the prefix, so wine sees the app as if it were normally installed on C:\ (registry entries pointing to C:\... keep working). Both layouts work: plain wine prefixes (drive_c at the top) and Proton-managed ones (drive_c under pfx/). The app stays tied to that prefix; removing the launcher entry never deletes files from the prefix.
"Open with PLWL" in the file manager
The desktop entry (MimeType + Exec %f) makes PLWL show up in Dolphin/Nautilus under Open With for Windows executables (.exe, .msi, .bat, .cmd, .lnk). Opening a file that way shows a small popup in the launcher where you pick the Wine/Proton version and the prefix for this run — both default to the launcher's defaults, nothing is imported into the library. A second launcher instance hands the path to the running one and exits (same single-instance mechanism the shortcuts use).
LAN syncing
Two PLWL installs on the same LAN can mirror each other's content - no cloud, no accounts. Open LAN syncing in the sidebar (under Settings):
- Device ID - 24 characters, generated once per install (current timestamp + random characters) and re-rollable at any time.
- Sync code - 8 characters, letters and digits, case-insensitive. A device only accepts a connection when the caller proves it knows its own code; each verification costs two seconds and a device may only have one in flight, so guessing over the LAN is pointless. Both the ID and the code can be re-rolled.
- Devices on your network - other PLWL installs, found over UDP; a device shows up only while PLWL is running there, and disappears a few seconds after it is closed.
Pick a device and choose what to push: portable apps, apps imported from a prefix, Wine/Proton builds and prefixes. The code has to be typed once - an accepted code is stored next to that device ID, so every later sync needs no typing. If the other side re-rolled its code, the stored one is forgotten and the launcher asks for the new one instead of failing silently.
Both machines show what is happening. The sender gets a progress popup (phase, files, how many games / prefixes / Wine builds take part, and the transferred vs. planned size in GB); the receiving device gets the same popup titled Receiving from X…, driven by the transfer as it arrives. A running sync is not cancellable from the outside: clicking the backdrop or pressing Escape does nothing, the popup closes itself when the transfer ends - or after five minutes without progress, when the other side has vanished.
The sending device is the source of truth: files that differ are overwritten, missing ones are written, and anything living only on the receiving side inside the synced trees (files/apps/, files/wines/, files/wineprefixes/, files/data/icons/) is deleted. Files are compared with a fast, collision-resistant hash (BLAKE2b-512, SHA-512/SHA-256 fallback); Force sync all files skips the comparison and overwrites everything instead. Everything else stays local: settings, logs, playtime/last played, translations, and external (leave) apps - prefixes are always kept usable, so app entries pointing inside a prefix keep their prefix-relative paths and the receiving side never loses its own Main prefix.
Wine & Proton support
- System Wine — uses the
winebinary from PATH. - Imported builds — drop any wine or Proton build into
files/wines/. The folder may contain the build directly, or one level of nesting (zip-extracted layouts are detected automatically). - Proton without Steam — fully supported. Proton is invoked like Steam does it:
STEAM_COMPAT_CLIENT_INSTALL_PATHpoints to a fake steam client folder,STEAM_COMPAT_DATA_PATHis a per-build compat folder, and the prefix lives at<compat>/pfxwhich PLWL links to its own prefix folder. No Steam installation required (GE builds work out of the box; for a few Valve builds that refuse to run without a client, PLWL fakes a minimal steam folder infiles/data/fake-steam).
Translations
All UI text comes from JSON files in files/translations/. The data object carries the language names; texts maps keys to strings, with {0}, {1} ... placeholders filled at runtime.
The translations bundled with a release are launcher-owned: on every start they are refreshed into files/translations/ whenever their content changed, so launcher updates deliver new/changed keys to existing installs. Extra language files the bundle does not ship (user-added) are never touched.
Development
Codebase overview, conventions and rules for contributors: development.md.