v0.5.9
[0.5.9] - 2026-05-27
Highlights
Multilingual UI, self-growing disk, and a guest that updates without a reinstall.
- The whole tray / GUI / CLI is now translatable and fully translated to 7 languages (en/ko/zh/ja/de/fr/it) — picked from your system locale, switchable with
winpodx languageor the GUI dropdown (fixes the stray-Korean reports, #335). - The Windows C: drive grows on its own when it fills up — and can be grown by hand with
winpodx pod grow-disk— including past the WinRE recovery partition dockur leaves behind (#318). - Guest sync: upgrading winpodx on the host now pushes the new agent / fixes / binaries into a running guest with no wipe-reinstall (
winpodx pod sync-guest, automatic on pod start). - Pod auto-start on login is now a real, opt-in feature (
winpodx autostart on). - Fixes: USB shortcut erroring with no media mounted, RemoteApp painting the logon screen (#332), AppImage
podman-compose ModuleNotFoundErroron atomic distros (#322), and a too-tight install agent-wait that gave up early.
Added
- Selectable, fully translated UI — 7 languages (en/ko/zh/ja/de/fr/it). winpodx's own tray / GUI / CLI text is now translatable, and all ~814 user-facing strings are wrapped and fully translated to all six non-English languages (placeholders, backtick command snippets, and product names preserved verbatim).
[ui] language(defaultauto) picks the language from the host locale ($LANG) and falls back to English; override it from the CLI (winpodx language ko, orwinpodx languageto show current) or the GUI Settings → winpodx UI language dropdown (applies on next launch). English is the source/baseline — always 100% complete — and any string a future language hasn't translated falls back to English (no blanks). Catalogs live atwinpodx/locale/<lang>.jsonas flat{english: translation}maps, so adding a language is a file drop with no code change. Addresses the stray-Korean reports (#335). - Pod auto-start on login (opt-in).
cfg.pod.auto_startwas a stored-but-unused flag; now it works — but it's off by default and explicitly opt-in (booting Windows on every login is heavy, so a plain install never forces it). Turn it on withwinpodx autostart on(or the GUI Settings checkbox): that installs the tray autostart entry and setsauto_start, so the tray — launched on login — starts the pod (or resumes it if suspended).winpodx autostart off/statusmanage it. Background + best-effort (a failure just leaves the pod stopped, logged; never crashes the tray); no-op when already running. - Guest sync — apply host updates to a running guest without a reinstall. Upgrading winpodx on the host used to leave the guest's
agent.ps1, urlacl reservation (#269), rdprrap/shim binaries, and registry fixes stale until a wipe-reinstall./oemis a live bind mount of the host'sconfig/oem, so after a host upgrade the container already has the new files; winpodx now delivers them into the running guest (same channel aspod recover-oem, but automated over the agent/exec), re-applies the idempotent fixes, restarts the agent (via a one-shot scheduled task so it doesn't kill the/execit's serving), and stamps the guest version (C:\winpodx\install-state\guest_version.json). Runs automatically once per pod start when the guest stamp is older than the host (guest_autosync, default on); also triggered bywinpodx migrate(so a package / AppImage / flatpak upgrade — whose update path never runsinstall.sh— gets the full guest refresh from a single command), manual viawinpodx pod sync-guest [--force], and a GUI Tools → Sync Guest action. No agent change. Seedocs/design/GUEST_SYNC_DESIGN.md. - Windows disk auto-grow + manual grow (#318). The Windows C: drive now grows on its own: when the system volume fills past
disk_autogrow_threshold_pct(default 80%) and the pod is idle, winpodx grows the virtual disk enough to restoredisk_autogrow_target_free_pctfree space (default 30%, in wholedisk_autogrow_incrementsteps — not a flat bump), recreates the container so dockur grows the image, then extends C: to fill viaResize-Partition— no manual Disk Management step. The grow is bounded by the host's free space (minus a safety reserve);disk_max_sizeis now an optional explicit ceiling (empty by default) rather than a fixed cap. The same operation is exposed manually:winpodx pod grow-disk(add one increment),winpodx pod grow-disk 128G(absolute target),winpodx pod grow-disk --extend-only(just extend C: into existing unallocated space), andwinpodx pod disk-usage(size / free / used%). The GUI Tools page gains a Grow Disk action. Auto-grow runs only while idle so it never interrupts a live RemoteApp session, and the guest-side work reuses the agent/execpath (no agent change). Default-on; setdisk_autogrow = falseto manage size manually. Note: dockur has no online disk resize, so each grow recreates the container (a quick guest reboot) — winpodx schedules auto-grows during idle for exactly this reason. dockur's Windows layout puts a WinRE Recovery partition right after C:, so the grown space lands behind it and a plainResize-Partitioncan't reach it; the extend step detects this, detaches WinRE, removes the blocking recovery partition, extends C: to fill, and re-enables WinRE (inC:\Windowswhen no dedicated partition remains). Reported by @drjwhitty (Linux Mint 22.2).
Fixed
- Upgrade re-install hung at
[4/4]waiting for the OEM reboot pass. Re-runninginstall.shover an already-provisioned guest frozepod wait-ready --logsat phase 4. Two causes: (1)--logs --tail 100replayed the original first-boot download log, and a stale wget ETA line inflated the wait deadline to tens of minutes; (2) phase 4 (_wait_for_oem_reboot) blocked for that whole inflated window when the agent was still transitioning, because the "marker never reappears → this is an upgrade" exit only fired on a clean probe, never while the agent was rejecting connections. Fixes: the deadline no longer extends once the container is running (any ETA line after that is replayed history); phase 4 is hard-capped at 180s (it's a marker poll, not a download); and the upgrade-path exit now triggers on the appear-grace clock regardless of probe outcome. - USB desktop shortcut errored when no removable media was mounted. install.bat always drops a
USBshortcut pointing at\\tsclient\media, but winpodx only redirected that drive when a removable-media base (/run/media/$USERetc.) existed — so clicking USB with nothing plugged in failed with "\\tsclient\mediais not accessible … Attempt to access invalid address." winpodx now always redirects amediadrive: the real base when mounted, otherwise an empty placeholder dir, so the shortcut opens to an empty folder instead of erroring. - Stray Korean text in the UI (#335). The tray "Quit" confirmation dialog and the CPU/RAM tier preset labels (
Low/Mid/High) were hardcoded in Korean, so an English-locale user got a Korean prompt on exit. Both are now English (winpodx's UI is English; a full selectable-UI-language i18n layer is planned separately). Reported by @camegone (CachyOS). - Install: agent-readiness wait is now dynamic + generous, with no misleading errors. On a slow first boot (cold cache / slow disk / a long ISO download that pushes the whole install late) the post-RDP agent
/healthwait was capped at a hard 180s, so it gave up early — leaking a scaryagent didn't answer within 180sWARN and then skipping apply-fixes / discovery even though the agent was just minutes from coming up. The wait now honors the caller's full (dynamic, ISO-ETA-extended) deadline —pod wait-readyphase 3 already passes the auto-extending deadline, so the agent gets as long as the install legitimately needs. Separately, the guest version stamp read/write now go through the windowless agent/execchannel (run_via_transport) instead of FreeRDP (#346) — so a transitioning agent on a fresh first boot fails clean and the stamp is re-attempted on the next pod start, rather than leaking a scaryFreeRDP timed out after 30s/ERRCONNECT_ACTIVATION_TIMEOUTwarning mid-install. The stamp is best-effort and surfaces at info level ("deferred; will retry next start"), never a warning. The post-install app-discovery retry budget was also raised from 3 to 6 attempts (~50s) so it outlasts the apply chain's TermService/rdprrap cycle instead of falling through to pending-resume on the next launch. - First-run setup prompt fired on every invocation (#341). "winpodx has not been set up yet" is gated on an internal
initializedflag, not on the config file existing. The non-interactive existing-config path printed "skipping setup" and returned before flipping that flag, so a config with it stillfalse(created via install.sh's own skip path, or written before the flag existed) made the prompt loop forever — pick "Auto", setup short-circuits, prompt returns next time. The skip path now marks the install initialized too. Reported by @ntruhan (Fedora 44). - RemoteApp launched into the logon/lock screen → corrupted render (#332). Apps sometimes came up showing the Windows login background instead of the app, with
xf_Pointer: Invalid appWindowspam — the app had launched, but FreeRDP's RAIL window was created while the guest session was still transitioning through the logon/lock screen (dockur's autologon session briefly re-spawns), so FreeRDP painted the stale logon framebuffer and never repainted the app. Version-independent (reproduced on current FreeRDP). winpodx now waits — best-effort, agent-only so it never flashes a FreeRDP probe window — until the guest console is interactive (explorer.exeup, noLogonUI.exe) before firing the RemoteApp connection; if the agent is unreachable or it times out, the launch proceeds as before. Reported by @tolistim (Mint 22.3). - AppImage:
podman-composeModuleNotFoundError(#322). The fat AppImage bundled Fedora's/usr/bin/podman-composelauncher script but not thepodman_composePython module it imports (it's pure Python, solddcan't pull it in), and the script's shebang fell through to the host'spython3— which lacks the module on atomic distros. Pod creation failed withModuleNotFoundError: No module named 'podman_compose'. Now the build pip-installspodman-composeinto the AppImage's bundled interpreter and ships ausr/bin/podman-composewrapper that runs it viapython3 -m podman_compose(a pip console script can't be used directly — its shebang is the dead build-time path, same reason AppRun usespython3 -m winpodx). Reported by @jmayniac (Bluefin / Fedora atomic).