It turns out the best terminal app for Windows is KDE's Konsole. This project contains a guide and tools to set Konsole up correctly in a Windows Subsystem for Linux container. Also includes KDE's solitaire card games for fun.
  • PowerShell 65.6%
  • Shell 34.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-11-03 10:37:07 -07:00
bin Use live config from local WSL container 2026-11-03 10:29:17 -07:00
config Use live config from local WSL container 2026-11-03 10:29:17 -07:00
windows Initial WSLg Konsole/KPatience guide, launchers, config and scripts 2026-11-03 16:50:44 +00:00
collect.sh Use live config from local WSL container 2026-11-03 10:29:17 -07:00
install.sh Initial WSLg Konsole/KPatience guide, launchers, config and scripts 2026-11-03 16:50:44 +00:00
README.md add Claude credit to README 2026-11-03 10:37:07 -07:00

WSLg Konsole and KPatience Nutshell Guide

Overview

This project was created with the help of Claude AI

It turns out the best terminal application for Windows is KDE's Konsole, running under Windows Subsystem for Linux. Konsole offers multiple-line tabs, the lack of which with Microsoft Terminal is a major setback.

This project provides a guide and utilities to run KDE's Konsole and KPatience (Klondike etc.) as native-looking Windows windows via WSLg.

This setup uses Wayland, dark Breeze colors, Oxygen widget style with wide scrollbars and arrows, Adwaita cursor at a sane size, integer scaling with ~20% larger fonts (fractional QT_SCALE_FACTOR leaves repaint slivers), Start menu shortcuts with proper icons, and taskbar pins that group with their windows.

How WSLg works

WSLg uses a hidden system distro which runs Weston (Wayland compositor) + XWayland + PulseAudio inside the WSL VM, and msrdc.exe on Windows displays each Linux window as its own Windows window over RDP RemoteApp.

Quick start

After the prerequisites, on the Linux side (from a clone of this repo):

./install.sh --packages

Then on Windows, from the repo's windows\ folder (reachable as \\wsl.localhost\Ubuntu\...):

powershell -ExecutionPolicy Bypass -File .\create-shortcuts.ps1

Finish with wsl --shutdown and the per-app AUMID tagging in section 7. Sections 1–9 explain each step and the reasons behind it.

After tweaking settings on the machine, copy the live files back into the repo, review, and commit:

./collect.sh && git diff

Repository layout

Path Installed to Purpose
install.sh — Deploy launchers, config and icons (--packages also runs apt)
collect.sh — Copy live files from the machine back into the repo
bin/wslg-qt /usr/local/bin/wslg-qt Default Qt/cursor/scale/Wayland settings for any Qt app
bin/org.kde.konsole /usr/local/bin/org.kde.konsole Konsole launcher used by the Konsole shortcut
config/kdeglobals ~/.config/kdeglobals Breeze Dark color values, UI fonts, widgetStyle=oxygen, icon theme
config/oxygenrc ~/.config/oxygenrc Scrollbar width 19, arrow buttons
config/konsolerc ~/.config/konsolerc Sets the default Konsole profile
config/konsole/WSLg.profile ~/.local/share/konsole/ Konsole profile: bash -l, font, clipboard paste, copy on select
windows/create-shortcuts.ps1 Start menu Create/update the Konsole and KPatience shortcuts
windows/get-window-aumid.ps1 — Show the AppUserModelID of each WSLg window
windows/set-lnk-aumid.ps1 — Tag a shortcut with an AppUserModelID

config/kdeglobals is BreezeDark.colors (Breeze 5.27, as on Ubuntu 24.04) with the font, style and icon lines added — see section 3.

1. Prerequisites

Update WSL (PowerShell). If it reports Wsl/UpdatePackage/0x80070656 (exit 1622), check wsl --version — the install usually succeeded and only the client-side MSI logging failed.

wsl --update

WSLg must not be disabled. In %USERPROFILE%\.wslconfig under [wsl2], remove guiApplications=false (default is on). Close VS Code WSL windows first — wsl --shutdown kills every WSL session.

wsl --shutdown

Verify inside Ubuntu: /mnt/wslg should list weston.log, versions.txt, etc., and both variables should be set.

ls /mnt/wslg && echo "DISPLAY=$DISPLAY WAYLAND_DISPLAY=$WAYLAND_DISPLAY" && ls -la /tmp/.X11-unix

2. Install packages

--no-install-recommends keeps out most of the KDE desktop (and Baloo). qtwayland5 is only "recommended", so it must be named explicitly for Wayland.

sudo apt update && sudo apt install --no-install-recommends konsole kpat qtwayland5 plasma-integration breeze breeze-icon-theme adwaita-icon-theme kde-style-oxygen-qt5 fonts-dejavu-core librsvg2-bin imagemagick

What each extra is for:

  • qtwayland5 — Qt5 Wayland platform plugin
  • plasma-integration — KDE platform theme (QT_QPA_PLATFORMTHEME=kde) that applies colors/style/icons from kdeglobals
  • breeze — provides BreezeDark.colors
  • breeze-icon-theme — toolbar/menu icons
  • adwaita-icon-theme — Adwaita cursor (has a 32 px size; Breeze cursors jump 24 → 36)
  • kde-style-oxygen-qt5 — Oxygen widget style (configurable scrollbar width)
  • librsvg2-bin, imagemagick — icon conversion

3. Theme and widget style

The KDE platform theme reads actual color values from [Colors:*] groups in kdeglobals; ColorScheme=BreezeDark alone is just a name and falls back to light. Build kdeglobals from the scheme file (what Plasma's System Settings does), then add style and icons:

cp /usr/share/color-schemes/BreezeDark.colors ~/.config/kdeglobals && printf '\n[KDE]\nwidgetStyle=oxygen\n\n[Icons]\nTheme=breeze-dark\n' >> ~/.config/kdeglobals

Oxygen scrollbar width (default 15) and arrow buttons. Breeze has no width setting and Konsole's terminal scrollbar ignores Breeze's arrow options.

printf '[Style]\nScrollBarWidth=19\nScrollBarAddLineButtons=1\nScrollBarSubLineButtons=1\n' > ~/.config/oxygenrc

Larger UI fonts (menus, tabs, dialogs) instead of fractional scaling:

sed -i '0,/^\[General\]/s//[General]\nfont=DejaVu Sans,12,-1,5,50,0,0,0,0,0\nmenuFont=DejaVu Sans,12,-1,5,50,0,0,0,0,0\ntoolBarFont=DejaVu Sans,12,-1,5,50,0,0,0,0,0/' ~/.config/kdeglobals

Style config is read at process start — pkill konsole before testing changes (new windows join the existing process).

4. Launcher wrappers

All Qt settings live in one generic wrapper. Each value is a default, so a caller can override it (e.g. QT_SCALE_FACTOR=1 wslg-qt kpat).

printf '#!/bin/sh\nexport XCURSOR_THEME="${XCURSOR_THEME:-Adwaita}" XCURSOR_SIZE="${XCURSOR_SIZE:-16}" QT_SCALE_FACTOR="${QT_SCALE_FACTOR:-1}" QT_QPA_PLATFORM="${QT_QPA_PLATFORM:-wayland}" QT_QPA_PLATFORMTHEME="${QT_QPA_PLATFORMTHEME:-kde}"\nexec "$@"\n' | sudo tee /usr/local/bin/wslg-qt >/dev/null && sudo chmod 755 /usr/local/bin/wslg-qt

Konsole launcher (used by the Konsole shortcut):

printf '#!/bin/sh\nexec /usr/local/bin/wslg-qt /usr/bin/konsole "$@"\n' | sudo tee /usr/local/bin/org.kde.konsole >/dev/null && sudo chmod 755 /usr/local/bin/org.kde.konsole

Why these values:

  • QT_QPA_PLATFORM=wayland — Qt5 won't pick Wayland on its own (WSLg doesn't set XDG_SESSION_TYPE); with no fallback, a window appearing proves Wayland works
  • XCURSOR_SIZE=16 — Qt multiplies by WSLg's output scale (2 at 250% Windows scaling), requesting 32 px; Xcursor themes only have fixed sizes and the nearest one wins
  • QT_SCALE_FACTOR=1 — keeps the device pixel ratio an integer (2.0); at fractional ratios (e.g. 2 × 1.2 = 2.4) partial repaints round badly and leave 1 px slivers of old content in both Konsole and KPatience. Enlarge fonts instead of scaling
  • wslg.exe doesn't read ~/.profile/~/.bashrc, so the variables must be in the wrapper

Changes to Qt settings go in /usr/local/bin/wslg-qt. Per-app overrides go in that app's shortcut arguments.

5. Konsole profile settings

Provided as config/konsole/WSLg.profile (made the default by config/konsolerc). Equivalent settings in Settings → Edit Current Profile:

  • General → Command: /bin/bash -l — login shell so ~/.profile (PATH additions) is read; -i is redundant on a pty
  • Mouse → Middle click: Paste from clipboard, plus Copy on select — WSLg only syncs CLIPBOARD with Windows, never PRIMARY
  • Appearance: terminal color scheme (Breeze default is already dark); font size ~20% larger than default to make up for scale 1

6. Windows Start menu shortcuts

Shortcuts go in the Start menu folder, not the desktop. Target is C:\Program Files\WSL\wslg.exe (GUI-subsystem launcher, no console window). windows/create-shortcuts.ps1 creates both, and install.sh builds the icons; the manual equivalents follow.

Konsole

Icon: Breeze ships utilities-terminal only as SVG, so render it first.

mkdir -p /mnt/c/Users/<user>/Icons && rsvg-convert -w 256 -h 256 /usr/share/icons/breeze/apps/64/utilities-terminal.svg -o /tmp/konsole-256.png && convert /tmp/konsole-256.png -define icon:auto-resize=256,128,48,32,16 /mnt/c/Users/<user>/Icons/konsole.ico

Shortcut (PowerShell):

$s=(New-Object -ComObject WScript.Shell).CreateShortcut("$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Konsole.lnk"); $s.TargetPath='C:\Program Files\WSL\wslg.exe'; $s.Arguments='-d Ubuntu --cd ~ -- /usr/local/bin/org.kde.konsole'; $s.IconLocation="$env:USERPROFILE\Icons\konsole.ico"; $s.Save()

WSLg can't use SVG icons (Icon SVG :0 in weston.log) and doesn't search 256x256, so also give it PNGs at standard sizes — this fixes WSLg's own "Konsole (Ubuntu)" Start entry:

for s in 128 96 64 48 32; do sudo mkdir -p /usr/share/icons/hicolor/${s}x${s}/apps && rsvg-convert -w $s -h $s /usr/share/icons/breeze/apps/64/utilities-terminal.svg | sudo tee /usr/share/icons/hicolor/${s}x${s}/apps/utilities-terminal.png >/dev/null; done

KPatience

KPatience ships PNG icons, so convert directly.

convert /usr/share/icons/hicolor/256x256/apps/kpat.png -define icon:auto-resize=256,128,48,32,16 /mnt/c/Users/<user>/Icons/kpat.ico

Shortcut (per-app overrides go before the wrapper, e.g. -- env QT_SCALE_FACTOR=1.5 /usr/local/bin/wslg-qt kpat):

$s=(New-Object -ComObject WScript.Shell).CreateShortcut("$env:APPDATA\Microsoft\Windows\Start Menu\Programs\KPatience.lnk"); $s.TargetPath='C:\Program Files\WSL\wslg.exe'; $s.Arguments='-d Ubuntu --cd ~ -- /usr/local/bin/wslg-qt kpat'; $s.IconLocation="$env:USERPROFILE\Icons\kpat.ico"; $s.Save()

7. Taskbar pin grouping

The taskbar groups by AppUserModelID (AUMID). The shortcut's identity is wslg.exe, but the window belongs to msrdc.exe, which tags each RemoteApp window with Microsoft.RemoteApp.<hash> — so a plain pin opens a second button. Fix by giving the shortcut the window's AUMID.

  1. Open the app, then read its window's AUMID with windows/get-window-aumid.ps1:
powershell -ExecutionPolicy Bypass -File .\get-window-aumid.ps1
  1. Unpin the old taskbar pin (a pin is a copy of the shortcut made at pin time).
  2. Tag the Start menu shortcut with windows/set-lnk-aumid.ps1:
powershell -ExecutionPolicy Bypass -File .\set-lnk-aumid.ps1 -Lnk "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Konsole.lnk" -Aumid "Microsoft.RemoteApp.<hash from step 1>"
  1. Verify with Get-StartApps | Where-Object Name -like 'Konsole*', then re-pin from Start. If grouping still fails, restart Explorer with Stop-Process -Name explorer.

The hash is msrdc-internal; if a WSL/msrdc update breaks grouping, repeat steps 1–4.

A taskbar pin is a snapshot: after changing a Start shortcut's arguments, unpin, pkill konsole, and re-pin, or the pin keeps running the old command. Inspect what a pin actually runs:

Get-ChildItem "$env:APPDATA\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar","$env:APPDATA\Microsoft\Windows\Start Menu\Programs" -Filter '*Konsole*.lnk' | ForEach-Object { $l=(New-Object -ComObject WScript.Shell).CreateShortcut($_.FullName); [pscustomobject]@{Lnk=$_.FullName; Args=$l.Arguments} } | Format-List

8. Known limitations

  • Tux icon on the running taskbar button. WSLg keys its app list by stripping the reverse-DNS prefix (org.kde.konsole.desktop → Key:konsole) but looks up windows by the full Wayland app ID (org.kde.konsole), finds nothing, and falls back to Tux. Not fixable by config (Qt5 has no app-ID override). Affects any org.kde.*/org.gnome.* app. Evidence: grep -n -i konsole /mnt/wslg/weston.log.
  • Title bar button spacing is hard-coded in whatever draws the Wayland decoration; no setting.
  • No file drag-drop or file clipboard to Windows — text only. Copy files to /mnt/c/... or pick them in Windows dialogs via \\wsl.localhost\Ubuntu\home\<user>\.
  • Cursor size is stepwise — themes contain fixed bitmap sizes (Breeze 24/36/48, Adwaita 24/32/48/64/96). Check with the Xcursor header reader in Troubleshooting.
  • Compensation values depend on Windows scaling — changing the display scale % or using a different-DPI monitor changes cursor/UI size.
  • Harmless stderr noise: libEGL warning/ZINK: failed to choose pdev (no /dev/dri in WSL; Konsole doesn't need GL) and kf.windowsystem: Could not find any platform plugin (kwayland-integration not installed; only affects raise/attention requests).

9. Troubleshooting

Symptom Cause Fix
DISPLAY/WAYLAND_DISPLAY empty, /mnt/wslg nearly empty guiApplications=false in .wslconfig, or shell from SSH/old tmux Remove the line, wsl --shutdown; use a fresh wsl -d Ubuntu shell
Window still light kdeglobals lacks [Colors:*] groups Rebuild from BreezeDark.colors (section 3)
Config change has no effect Old Konsole process still running pkill konsole, relaunch
Huge cursor No cursor theme / size multiplied by output scale Adwaita + XCURSOR_SIZE=16
1 px lines/slivers of old content (Konsole rows, KPatience cards) Fractional device pixel ratio Keep QT_SCALE_FACTOR=1, enlarge fonts
Pin opens a second taskbar button AUMID mismatch Section 7
Pin ignores changes to wslg-qt Pin is a stale copy with old arguments (an explicit env value overrides the wrapper's defaults) Fix the Start shortcut, unpin, re-pin (section 7)
Start entry shows Tux Icon only exists as SVG, or not at a size WSLg searches PNGs in hicolor/96x96 etc. (section 6)

List the bitmap sizes in a cursor theme:

python3 -c "import struct,sys;d=open(sys.argv[1],'rb').read();n=struct.unpack('<I',d[12:16])[0];print(sorted({struct.unpack('<III',d[16+12*i:28+12*i])[1] for i in range(n)}))" /usr/share/icons/Adwaita/cursors/left_ptr

Check what WSLg resolved for an app:

grep -n -A8 'org.kde.konsole.desktop' /mnt/wslg/weston.log | grep -E 'Icon (file|image)|Key:'

10. File reference

Location Purpose
%USERPROFILE%\.wslconfig Global WSL settings (guiApplications must not be false)
~/.config/kdeglobals Dark color values, UI fonts, widgetStyle=oxygen, icon theme
~/.config/oxygenrc Scrollbar width 19, arrow buttons
/usr/local/bin/wslg-qt Default Qt/cursor/scale/Wayland settings for any Qt app
/usr/local/bin/org.kde.konsole Konsole launcher → wslg-qt konsole
/usr/share/icons/hicolor/*/apps/utilities-terminal.png PNG icons for WSLg (not package-owned; remove manually if Konsole is removed)
%USERPROFILE%\Icons\konsole.ico, kpat.ico Shortcut icons
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Konsole.lnk, KPatience.lnk Shortcuts (AUMID-tagged for pin grouping)
~/.config/konsolerc, ~/.local/share/konsole/WSLg.profile Default Konsole profile and its settings
get-window-aumid.ps1, set-lnk-aumid.ps1 Read a window's AUMID / tag a shortcut with it (in the repo's windows/)
/mnt/wslg/weston.log WSLg compositor log: app list, icons, scaling, window app IDs