Software / Unified Base / Guide

Unified Base — Setup Guide

Most of Unified Base explains itself: add a folder, press Start. The part that does not is crossing operating systems — Windows programs on Linux through Wine, Linux programs on Windows through WSL. Wine downloads itself; WSL takes a one-time install on Windows. That is all here, along with the rest.

Installing and running it

The installers carry their own Python and Qt, so nothing needs to be there first, and both install for your user only — no admin password, no root. Download them from the Unified Base page or the project’s GitHub releases.

Windows installer

Run UnifiedBase-windows-x64-setup.exe. It is not code-signed yet, so SmartScreen may say Windows protected your PC: click More info, then Run anyway. It goes to %LOCALAPPDATA%\Programs\Unified Base and puts a Unified Base folder on the Start menu: the app, its self-test, Set Up Linux Programs (WSL) and the Read Me. Uninstall it from Settings ▸ Apps; it asks before deleting your modules and settings.

Linux package

For Mint 21, Ubuntu 22.04, Debian 12 or newer. Extract UnifiedBase-linux-x86_64.tar.gz and double-click Install Unified Base — the file manager may ask you to trust it first — or run ./install.sh in a terminal. It installs to ~/.local, adds Unified Base to the menu under Development and a unified-base command, and checks it starts before it says it is done. Uninstall Unified Base in the same folder removes it and leaves your modules and settings alone.

Either way, File ▸ Load Demo Modules is the quickest way to see it work.

From source, on Linux

From the Unified Base folder, run ./run.sh. The first run makes its own Python environment in .venv and installs PySide6 and python-xlib into it — user-level pip, nothing system-wide. Embedding needs X11 window ids, so on a Wayland desktop it runs itself, and every module, through XWayland automatically.

From source, on Windows

Double-click run.bat. It needs Windows 10 version 1809 or later (or Windows 11) and Python 3. If Python is missing:

winget install -e --id Python.Python.3.13

The first run makes .venv and installs PySide6 and psutil, then starts in a console window that hides itself.

Check a new machine

Unified Base Self-Test on the Start menu, unified-base --selftest on Linux, or ./run.sh --selftest / run.bat --selftest from source opens a small window, finds it, embeds it, stops it, and reports whether Wine, WSL and a browser are there, and for each language whether it is fetched, already on the system, or will download on first use. Run it once on any machine you are setting up; it tells you what the rest of this guide will need.

Adding modules

A Python module that ships its own venv (.venv, venv or env) runs from that, untouched. Otherwise it gets a private one under .unified_base/envs, with dependencies from its requirements files, its pyproject, and a scan of the modules it actually imports.

The File menu with Load Demo Modules open, offering Linux (19), Windows (22) or All
The demos come in two groups, and either OS can load both.

Languages it gets for you

The first start of a module gets its language when the machine lacks it, or has one older than the project needs: Node.js 24, the .NET 10 SDK, Java 25 with Maven, and Rust (through rustup) on both systems; on Windows also Ruby 3.4 and PHP 8.4; on Linux, for Windows programs, Wine 11. Each downloads once into your own folder — no password, no admin prompt — and every module uses it from then on. The log says why it is fetching (“node here is 12.22, older than the 22.12+ it needs”), and each download is pinned and checked against its SHA-256 before it is used. The first .NET (229 MB on Linux, 287 MB on Windows) or Java (135 MB) module takes a few minutes; later ones start straight away.

“Older than it needs” comes from the project itself where it says: its .NET target, its Java release, its Node engine, its Rust version. This matters on long-term-support releases: Linux Mint 21 ships Node 12, Rust 1.75 and Java 11, which today’s Electron, crates and Maven builds refuse. Rust on Windows uses its GNU toolchain, which brings its own linker, so Visual Studio is not needed.

A few tools still come from the system. On Linux, PHP, Ruby and Docker come from your package manager: a module that needs one shows ⤓ Install in its header, behind the system’s own password prompt. On Windows, Docker Desktop, Go, CMake and make install through winget the same way (Windows asks in its own prompt), and the new tool is found without restarting anything. Where there is no package — Gradle, Composer — the log names the download page instead.

Unified Base never asks for your password and never types one. When an install needs admin rights, it is your system’s own prompt that asks.

Runs on, and the mark on the tab

Every module records what it needs, and the launcher works out how to provide it on the machine it is on:

Module needsOn LinuxOn Windows
Runs anywhere — most source projectsnativenative
Windows only — an .exe, a WinForms or WPF projectWinenative
Linux only — an ELF binary, a GTK or X11 programnativeWSL

Detection only trusts strong evidence: a binary’s own header, a project targeting Windows, an import that exists only on one OS. When it guesses wrong, right-click the tab ▸ Runs on. The choice is saved with the module, so the same module does the right thing when it is opened on the other OS.

A module tied to one OS shows a small mark on its tab — Windows’ four panes or a Tux — and hovering it says how it runs here, for example “Windows app · runs through Wine here”. A module that runs anywhere gets no mark.

The right-click menu on a tab with Runs on open: Runs anywhere, Linux only, and Windows only (via Wine here) ticked
The submenu says how it will be run on this machine, not only what the module needs.

Windows programs on Linux (Wine)

Nothing to install. Without Wine 10 or newer on the machine, the first Windows module you start downloads Wine 11 (70 MB, a portable build that needs no 32-bit libraries), then builds a shared Wine prefix at ~/.unified_base/wine/default, which takes a minute; every start after that is quick. Wine draws ordinary X11 windows, so Windows programs embed into panes the same way Linux ones do.

Windows-only Node.js and PHP programs, and Windows containers, are the exceptions: the tab explains why it cannot run them rather than trying.

Six Windows-only programs running on Linux through Wine, every tab marked with the Windows logo
Six Windows-only programs on Linux, each embedded in its own pane. The status line on each says “Wine”.

Linux programs on Windows (WSL)

Set Up Linux Programs (WSL) on the Start menu — also behind a Linux module’s Set up WSL button — does the three steps below, asking before each change: WSL and Ubuntu, what Linux modules need inside it (Python’s venv and Tk, gcc for Rust, the GUI libraries Electron, Java and Avalonia load), VcXsrv, and the .wslconfig line. To do it by hand instead:

1. Install WSL

In an administrator PowerShell, then restart when it asks:

wsl --install

Setup steps, the launch and the command bar all run inside the default distro, so a Linux module’s toolchains have to exist inside it. Node.js, .NET, Java with Maven, and Rust fetch themselves there, as they do on Linux. Ubuntu ships without a few things they lean on:

sudo apt install python3-venv python3-tk gcc

That one is run in the Linux terminal, not PowerShell. A module that needs anything else says which apt line to run.

2. An X server, so the windows can be embedded

Windows’ own Linux display, WSLg, draws its windows in a way that cannot be taken into another program. VcXsrv can:

winget install marha.VcXsrv

Start it with these options — a shortcut in your Startup folder does it at sign-in:

vcxsrv.exe :0 -multiwindow -clipboard -wgl -listen tcp

3. Let WSL reach it

Add this to %USERPROFILE%\.wslconfig (create the file if there is none), then run wsl --shutdown once:

[wsl2]
networkingMode=mirrored

With both in place, Linux programs open on VcXsrv and embed like any other window. Without them they still run, through WSLg, in their own windows beside the launcher. VcXsrv draws in software, so a full-window animation costs about one CPU core.

A module on a removable drive works too: Unified Base mounts the drive inside WSL the first time it is needed, because WSL only mounts fixed drives by itself.

Arranging the panes

Every module that is not Independent shares the main area, in one of two arrangements from the View menu:

Pane minimum size — Small (400×300), Medium (520×380) or Large (760×560) — is how small a pane may get before the view scrolls. Even out panes puts them back to equal widths. Tab colors paints tabs plain, with a small chip per language, or entirely in the language’s colours. Resource meters turns the CPU and memory strips on or off.

A narrow pane folds its header: first the buttons lose their words and keep their symbols, then everything that will not fit moves into a ☰ menu at the end.

Modules in a single row that scrolls sideways, one narrow pane’s ☰ menu open
Nothing is lost when a pane is narrow — it moves into the ☰ menu.

Logs, the command bar and the terminal

Logs in a pane’s header shows that module’s output — setup, build, its own stdout and stderr. The ▾ beside it decides where: In the pane (the log takes over the pane), Docked beside the module, or Separate window. Each module’s log is also written to .unified_base/logs.

A PHP module with its dev server log docked beside it, and the log-mode menu open on the module below
A docked log beside the PHP demo, and the ▾ menu that moves it.

Under the log is the command bar: type a command, press Enter, and it runs once in the module’s folder — through its bridge, so a Linux module’s command runs in WSL on Windows. For a Python module running natively it runs in the module’s own venv, so pip install rich lands where the module will find it. Pipes and && work; programs that need a real terminal do not.

For those, tick Terminal: a real one opens in the same folder, embedded under the log — xterm on Linux, the Windows console on Windows. Typing exit folds it away; ticking it again gives a fresh one. It opens a plain shell, so activate the module’s venv in it yourself if you need it.

A Python module’s pane showing pip installing rich from the command bar, with a terminal open below it
The command bar’s pip install went into the Python demo’s venv; the terminal below is xterm, embedded.

Per-module settings

Right-click a tab:

EntryWhat it does
Rename…The name on the tab. Double-clicking the tab does the same.
Save to ModulesKeep it in the library, so the Modules menu opens it in one click next time.
Scan for Sub-modules…The other runnable entries in its folder — Python files with a __main__ guard, extra package.json scripts. Tick the ones you want and each opens as its own tab, sharing this one’s runtime and settings.
Re-detect runtimeLook at the folder again. For a project that has changed shape, or a blank tab you have started filling.
Independent (fills window)Take the whole window, with the tab bar still there to switch back.
Embed windowOff, and the module always opens in its own window, with no wait for an embed.
Use shared environmentRun from one shared venv rather than a private one — handy when several modules need the same heavy dependencies. Takes effect on the next start.
Resource meterThe CPU and memory strip in this pane’s header.
Log viewIn the pane, docked beside the module, or a separate window.
Startup args…Appended to the command line. For npm they are passed through to the script, not swallowed by npm.
Environment variables…Set for every launch. EXTRA_PIP_PACKAGES adds pip packages the import scan missed. WINEPREFIX gives a Windows module a Wine prefix of its own.
Runs onRuns anywhere, Linux only, or Windows only — with how that is carried out on this machine.
Custom commands…A setup command and a run command of your own, for anything the detector does not know.
Close (remove from base)Removes the tab. The project folder and its environment stay on disk.

Rebuild Env in the header wipes the module’s environment — the venv, node_modules, target, build — and sets it up again. ⊞ Embed retries pulling a running module’s window into its tab.

The library and layouts

Open tabs come back the next time you start Unified Base. Beyond that:

Keyboard reference

The Run keys act on the picked tab, not on whatever pane the mouse is over. While you are typing into a module’s own window the keys are that program’s; click the tab bar to hand them back.

KeyAction
F5Start the picked module
Shift+F5Stop it — during setup, this cancels the setup
Ctrl+RRestart it
Ctrl+Shift+RRebuild its environment from scratch (asks first if it is running)
Ctrl+PgDown · Ctrl+PgUpNext or previous module
Ctrl+1 … Ctrl+9Jump straight to that module
Ctrl+WClose the module (its folder and environment stay on disk)
Ctrl+Shift+WClose All Modules… — every tab at once, after one question
Ctrl+NAdd Module…
Ctrl+Shift+NScan Folder for Modules…
Ctrl+TNew Blank Tab
Ctrl+SSave Layout As…
Ctrl+QExit
Double-click a tabRename it

Where your files live

Everything Unified Base keeps is in one folder in your home: ~/.unified_base on Linux, %USERPROFILE%\.unified_base on Windows. Your projects stay where they are; it only reads them and builds in them.

In .unified_baseWhat it is
modules.jsonThe open tabs and every module’s settings
library.jsonModules saved to the library
layouts.jsonSaved layouts
prefs.jsonView settings, window position, recent folders
envs/Python venvs it made, one per module, plus _shared
logs/One log file per module
wine/The shared Wine prefix (Linux)
toolchains/The languages it fetched for modules (Rust goes to ~/.cargo)
downloads/Downloads: installers it keeps, such as the Windows builds Wine modules use
unified_base.logAnything that went wrong inside the launcher itself

When something goes wrong

A module’s window opened outside the tab.
Press ⊞ Embed to try again. A module that never produces a window it can take — within about 40 seconds — gets a control panel in its tab instead and runs in its own window.
An Electron module quits at once, and the log talks about a sandbox.
On Ubuntu and other distributions that restrict unprivileged user namespaces, the Electron that npm installs cannot start its sandbox. The log gives the commands that fix it with the sandbox kept on; ⚑ Retry without sandbox in the header starts it without one instead.
A Linux module on Windows opens in its own window.
VcXsrv is not running, or networkingMode=mirrored is not in .wslconfig — see Linux programs on Windows.
A Linux module on Windows cannot find a tool.
Toolchains have to be inside the WSL distro, not on Windows. Node.js, .NET, Java, Maven and Rust fetch themselves there; for anything else the log says which apt line it needs. Rust also needs gcc, which Set Up Linux Programs (WSL) installs.
A Windows program on Linux shows boxes instead of text.
Java programs under Wine look for Arial, Times New Roman and Courier New, which a fresh Wine prefix does not have, and fall back to symbol fonts. It is a known gap in this beta; WinForms, Win32, Python and Ruby programs are not affected.
A WPF program closes as soon as it starts under Wine.
WPF does not run under Wine yet. WinForms and plain Win32 programs do.
A Docker module fails to build.
The log says why in plain words — the engine is not running, your account is not in the docker group, or the image is the wrong kind of container for the engine — and what to do about it.
Something in the launcher itself went wrong.
It keeps running and writes the error to .unified_base/unified_base.log. That file, and the self-test’s output, are the things to send if you report a problem. Questions and ideas go to Discussions.

← Back to Unified Base