cheat sheet
wsl
Install, list, export, import, configure, and clone WSL distributions using the wsl.exe command on Windows 10 and 11.
wsl — Managing Linux Distros from the wsl.exe CLI
What it is
wsl.exe is the management front-end for the Windows Subsystem for Linux — the tool you use to install distributions, list and configure them, export them as portable tarballs, and shut their virtual machines down cleanly. Microsoft ships it as a built-in command on Windows 10 (2004+) and Windows 11, evolved through several generations from "Windows Insider preview" feature to a properly versioned package on the Microsoft Store. This page is about wsl.exe itself; for the interop layer that lets you call Linux from PowerShell and Windows binaries from bash (/mnt/c, wslpath, notepad.exe from inside Ubuntu), see wsl-interop.
What's new in 2026
Active development is fast — releases are weekly on the WSL GitHub. Notable versions as of late May 2026:
| Version | Released | Highlights |
|---|---|---|
| 2.7.7 (pre-release) | 2026-05-19 | Bumps bundled Microsoft.WSL to 1.0.73.2 |
| 2.7.5 (pre-release) | 2026-05-15 | Kernel 6.18.26.1 (was 6.6 LTS); fixes VHD permissions for user-supplied volumes |
| 2.7.3 (stable) | 2026-04-25 | Settings UI tracks pending changes; ARM64 test-distribution support; IPv6 support for mirrored-mode networking |
| 2.7.1 | 2026-03-24 | Security patch for CVE-2026-26127 (.NET runtime update); VirtioFS elevated-access fixes; DNS-tunneling networking option |
Headline improvements landed across this line:
- Linux 6.18 LTS kernel — the WSL2 kernel jumped from 6.6 LTS to 6.18 LTS, which unlocks F2FS and ExFAT filesystem support and brings substantially newer eBPF and io_uring code.
- Cross-filesystem performance — Microsoft is shipping a multi-release initiative to speed up
/mnt/caccess. Reads/writes from Linux into the Windows filesystem and back are noticeably faster on small files, addressing the long-standing thousands-of-tiny-files pain point. - Networking — IPv6 finally works under mirrored mode (
networkingMode=mirroredin.wslconfig), and DNS tunneling is now an option to route Linux DNS queries through the Windows resolver. wsl --updateis the right way to take these — it pulls the latest packagedMicrosoft.WSLfrom the Microsoft Store regardless of how you originally installed.
wsl --update
wsl --version
Output:
WSL version: 2.7.5.0
Kernel version: 6.18.26.1
WSLg version: 1.0.66
MSRDC version: 1.2.6128
Direct3D version: 1.611.1-81528511
DXCore version: 10.0.27201.1000-241004-1359.ge-release
Windows version: 10.0.26200.5074
Install
WSL ships as an in-box optional component on modern Windows. The --install subcommand bootstraps everything in one shot: enables the optional features, downloads the latest kernel, sets WSL 2 as the default version, and installs Ubuntu as the initial distro.
# One-line install (Windows 10 2004+ / Windows 11)
wsl --install
# Install without a default distro (just the platform)
wsl --install --no-distribution
# Install a specific distro from the online catalogue
wsl --install -d Ubuntu-22.04
# List the catalogue first
wsl --list --online
Output (wsl --install):
Installing: Virtual Machine Platform
Virtual Machine Platform has been installed.
Installing: Windows Subsystem for Linux
Windows Subsystem for Linux has been installed.
Downloading: Ubuntu
Installing: Ubuntu
Distribution successfully installed. It can be launched via 'wsl.exe -d Ubuntu'
The requested operation is successful. Changes will not be effective until the system is rebooted.
Syntax
wsl.exe is a verb-style CLI: every operation is a long-option flag, optional flags come before any command you want to run inside the distro, and a literal -- separates the two.
wsl.exe [Argument] [Options...]
wsl.exe -d <Distribution> [-u <User>] [-- <command> [args...]]
Output: (none — exits 0 on success)
Essential options
| Option | Meaning |
|---|---|
--install [-d <Distro>] | Install WSL and (optionally) a specific distro |
--list, -l | List installed distros (--verbose, --quiet, --all, --running) |
--list --online | Show distros available from the Microsoft Store catalogue |
--set-default <Distro>, -s | Set the default distro |
| `--set-default-version <1 | 2>` |
| `--set-version <1 | 2>` |
--export <Distro> <File> | Save the distro filesystem to a tarball |
--import <Name> <Path> <File> | Create a new distro from a tarball |
--import-in-place <Name> <vhdx> | Re-attach an existing ext4.vhdx as a distro |
--unregister <Distro> | Delete a distro and its disk |
--terminate <Distro>, -t | Stop a running distro |
--shutdown | Stop all distros and the WSL VM |
--update | Update the WSL kernel |
--status | Show overall WSL status |
--version, -v | Show WSL version info |
-u <user> | Run as a specific user |
-d <distro> | Target a specific distro |
--cd <path> | Set working directory inside the distro |
--exec, -e | Execute without launching a login shell |
Listing distros — wsl --list
wsl --list enumerates installed distros. Without flags it prints just the names; --verbose adds the running state and WSL version, --quiet prints raw names suitable for scripting, and --all includes distros that aren't usable (e.g. mid-install). The asterisk in --verbose marks the default distro.
# Human-readable
wsl --list --verbose
wsl -l -v
# Only running distros
wsl --list --running
# Scripting — bare names, no decoration
wsl --list --quiet
# Show what the Store catalogue knows about
wsl --list --online
Output (wsl --list --verbose):
NAME STATE VERSION
* Ubuntu-22.04 Running 2
Ubuntu-20.04 Stopped 2
Debian Stopped 2
Alpine Stopped 1
Output (wsl --list --online):
The following is a list of valid distributions that can be installed.
Install using 'wsl.exe --install <Distro>'.
NAME FRIENDLY NAME
Ubuntu Ubuntu
Debian Debian GNU/Linux
kali-linux Kali Linux Rolling
Ubuntu-22.04 Ubuntu 22.04 LTS
Ubuntu-24.04 Ubuntu 24.04 LTS
OracleLinux_7_9 Oracle Linux 7.9
OracleLinux_8_7 Oracle Linux 8.7
OracleLinux_9_1 Oracle Linux 9.1
openSUSE-Leap-15.6 openSUSE Leap 15.6
SUSE-Linux-Enterprise-Server-15.5 SUSE Linux Enterprise Server v15.5
openSUSE-Tumbleweed openSUSE Tumbleweed
WSL versions — 1 vs 2
WSL 1 implements Linux syscalls as a translation layer over the Windows NT kernel; WSL 2 runs a real Linux kernel inside a lightweight Hyper-V utility VM. WSL 2 is faster for filesystem-heavy work on the Linux side, supports Docker and systemd, and is the default for new installs. WSL 1 still wins for cross-filesystem access (reading /mnt/c is much faster) and for cases where you cannot afford the VM's RAM overhead. You can mix versions across distros on the same machine.
# Show the WSL 2 kernel version and date
wsl --status
# Set the default version for any new installs
wsl --set-default-version 2
# Convert an existing distro to WSL 2 (can take minutes — it's a real move)
wsl --set-version Ubuntu-22.04 2
# Convert back to WSL 1
wsl --set-version Alpine 1
# Update the WSL 2 kernel
wsl --update
wsl --update --pre-release # opt into preview kernels
Output (wsl --status):
Default Distribution: Ubuntu-22.04
Default Version: 2
Windows Subsystem for Linux was last updated on 4/29/2026
WSL automatic updates are on.
Kernel version: 5.15.146.1-2
Output (wsl --set-version Ubuntu-22.04 2):
Conversion in progress, this may take a few minutes.
For information on key differences with WSL 2 please visit https://aka.ms/wsl2
Conversion complete.
Setting a default distro
Without -d every wsl invocation targets the default distro. Use --set-default to pick which one — handy if you keep an experimental distro around but want everyday work to land in your main one.
# Make Ubuntu-22.04 the default
wsl --set-default Ubuntu-22.04
wsl -s Ubuntu-22.04 # short form
# Verify
wsl --status
# Run a one-off command in a non-default distro without changing the default
wsl -d Debian -- cat /etc/os-release
Output (wsl --set-default Ubuntu-22.04):
The operation completed successfully.
Output (wsl -d Debian -- cat /etc/os-release):
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
…
Running commands without entering the shell
Pass arguments after the distro flag (or after a -- separator) to run a single command in the distro and exit. The command runs under your default Linux user unless you override with -u. Combine with PowerShell pipelines for cross-OS scripting.
# Run as the default user
wsl -d Ubuntu-22.04 ls -la /etc
# Be explicit about command boundary (recommended)
wsl -d Ubuntu-22.04 -- ls -la /etc
# Run as root for one command
wsl -d Ubuntu-22.04 -u root -- apt update
# Change working directory before running
wsl -d Ubuntu-22.04 --cd ~/projects -- git status
# Pipe Windows output into a Linux tool
Get-ChildItem C:\logs *.txt | wsl -d Ubuntu-22.04 -- wc -l
# Capture Linux output back into PowerShell
$pkgs = wsl -d Ubuntu-22.04 -- dpkg -l | Select-String 'ii python3-'
Output (wsl -d Ubuntu-22.04 --cd ~/projects -- git status):
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
Stopping distros — terminate and shutdown
--terminate stops a single distro's running processes and frees its memory while leaving the WSL VM itself alive. --shutdown halts every distro and the underlying utility VM — the only reliable way to reclaim all VM-allocated RAM or to apply changes to .wslconfig.
# Stop a specific distro
wsl --terminate Ubuntu-22.04
wsl -t Ubuntu-22.04
# Bring everything down (and the WSL VM itself)
wsl --shutdown
# Check what's still running
wsl --list --running
Output (wsl --shutdown):
The operation completed successfully.
Output (wsl --list --running afterwards):
There are no running distributions.
Export and import — tarball backups
--export dumps a distro's filesystem to a .tar file you can copy elsewhere — a quick way to back up before risky changes, share a fully-configured environment with a coworker, or move WSL to a different drive. --import rehydrates one of these tarballs into a new distro with a name and disk location of your choice. The --vhd option exports as a VHDX (ext4.vhdx) for direct re-attachment with --import-in-place.
# Back up a distro (the distro can be running)
wsl --export Ubuntu-22.04 D:\backups\ubuntu-22.04-$(Get-Date -f yyyyMMdd).tar
# Export as VHDX (PS to skip the tar conversion)
wsl --export Ubuntu-22.04 D:\backups\ubuntu-22.04.vhdx --vhd
# Restore as a new distro with its own disk location
New-Item -ItemType Directory D:\WSL\ubuntu-restored -Force
wsl --import Ubuntu-Restored D:\WSL\ubuntu-restored D:\backups\ubuntu-22.04-20260524.tar
# Import a pristine OS tarball (e.g. from Docker Hub)
docker pull alpine:3.20
docker save alpine:3.20 -o alpine.tar
wsl --import Alpine D:\WSL\alpine alpine.tar
# Re-attach an existing VHDX in place (no copy, fastest)
wsl --import-in-place Ubuntu-Restored D:\WSL\ubuntu-restored\ext4.vhdx
# Verify the new distro
wsl --list --verbose
Output (wsl --export ... .tar):
Export in progress, this may take a few minutes.
The operation completed successfully.
Output (wsl --list --verbose after import):
NAME STATE VERSION
* Ubuntu-22.04 Stopped 2
Ubuntu-Restored Stopped 2
Alpine Stopped 2
Unregister — delete a distro permanently
--unregister removes a distro and deletes its underlying disk image (the ext4.vhdx). There is no recycle bin and no undo — always --export first if there is any chance you'll want the data back. Useful for tearing down throwaway experiments and freeing disk.
# Tear down a distro completely
wsl --unregister Ubuntu-Restored
# Verify it's gone
wsl --list --verbose
Output:
The operation completed successfully.
NAME STATE VERSION
* Ubuntu-22.04 Stopped 2
Alpine Stopped 2
Per-distro configuration — /etc/wsl.conf
wsl.conf lives inside the distro at /etc/wsl.conf and controls how that one distro boots — its default user, whether systemd is enabled, how /mnt/c is mounted, networking settings, and which Windows PATH entries leak into Linux. Edits take effect after a wsl --terminate <distro> (or full wsl --shutdown); a plain logout is not enough.
# /etc/wsl.conf — runs inside Ubuntu
sudo tee /etc/wsl.conf <<'EOF'
[boot]
systemd=true
[user]
default=alicedev
[automount]
enabled=true
root=/mnt/
options="metadata,uid=1000,gid=1000,umask=022,fmask=033,case=off"
mountFsTab=true
[interop]
enabled=true
appendWindowsPath=false
[network]
generateHosts=true
generateResolvConf=true
hostname=myhost-ubuntu
EOF
# Apply: terminate and restart the distro
exit
Output: (none — exits 0 on success)
# In PowerShell — bounce the distro to load the new config
wsl --terminate Ubuntu-22.04
wsl -d Ubuntu-22.04 -- systemctl --version
Output (after the restart, systemctl --version):
systemd 249 (249.11-0ubuntu3.12)
+PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL …
Global configuration — %USERPROFILE%.wslconfig
.wslconfig lives on the Windows side at %USERPROFILE%\.wslconfig and controls the WSL 2 utility VM as a whole — how much RAM and how many CPUs to allocate, swap size, kernel command line, and whether to use the experimental "mirrored" networking mode. Changes require a wsl --shutdown to take effect.
# Create or edit .wslconfig
notepad "$env:USERPROFILE\.wslconfig"
Output: (none — opens Notepad on the file)
# Save as %USERPROFILE%\.wslconfig
[wsl2]
memory=8GB
processors=4
swap=4GB
swapfile=D:\\WSL\\swap.vhdx
localhostForwarding=true
# WSL 2025+ networking
networkingMode=mirrored
firewall=true
dnsTunneling=true
autoProxy=true
# Disable the experimental memory reclaim if it's causing trouble
[experimental]
autoMemoryReclaim=disabled
sparseVhd=true
Output: (none — this is the file content)
# Force the VM to restart so .wslconfig is re-read
wsl --shutdown
# Verify
wsl -d Ubuntu-22.04 -- free -h
wsl -d Ubuntu-22.04 -- nproc
Output (free -h after setting memory=8GB):
total used free shared buff/cache available
Mem: 7.8Gi 312Mi 7.1Gi 2.0Mi 370Mi 7.2Gi
Swap: 4.0Gi 0B 4.0Gi
Output (nproc after setting processors=4):
4
WSLg — running Linux GUI apps
WSLg (WSL GUI) ships built-in with WSL on Windows 11 (and recent Windows 10 builds via the Store app). Any Linux GUI program — gedit, eog, firefox, even full IDEs — opens in its own native Windows window with shared clipboard and audio. No XLaunch, VcXsrv, or DISPLAY plumbing needed.
# Install a sample GUI app
sudo apt update
sudo apt install -y nautilus eog mpv
# Run it — it opens in a native Windows window
nautilus
# Audio works out of the box (PulseAudio bridged to Windows)
mpv /mnt/c/Users/alicedev/Music/sample.mp3
Output: (none — Linux GUI apps launch in native Windows windows)
# Verify WSLg is enabled (Windows side)
wsl --version
Output (wsl --version):
WSL version: 2.3.24.0
Kernel version: 5.15.153.1-2
WSLg version: 1.0.65
MSRDC version: 1.2.5326
Direct3D version: 1.611.1-81528511
DXCore version: 10.0.26100.1-240331-1435.ge-release
Windows version: 10.0.22631.4391
Resizing or moving a distro's disk
WSL 2 stores each distro's filesystem in a sparse ext4.vhdx. Over time it grows on demand but never shrinks. To reclaim space, compact the VHDX with Optimize-VHD (Hyper-V module) or use the supported wsl --shutdown + diskpart shrink. To move a distro to a faster drive, export → unregister → import-in-place.
# 1. Find the VHDX
$distro = "Ubuntu-22.04"
$key = (Get-ChildItem 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss' |
Where-Object { (Get-ItemProperty $_.PSPath).DistributionName -eq $distro }).PSChildName
$path = (Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss\$key").BasePath
$vhdx = Join-Path $path 'ext4.vhdx'
$vhdx
# 2. Shutdown WSL so the VHDX is closed
wsl --shutdown
# 3. Compact it (requires Hyper-V or Diskpart)
Optimize-VHD -Path $vhdx -Mode Full
# 4. Move to another drive (export → unregister → import-in-place)
wsl --export $distro D:\backups\ubuntu.tar
wsl --unregister $distro
New-Item D:\WSL\ubuntu -ItemType Directory -Force | Out-Null
wsl --import $distro D:\WSL\ubuntu D:\backups\ubuntu.tar
wsl --set-default $distro
Output ($vhdx):
C:\Users\alicedev\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu22.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx
Common pitfalls
- Editing
wsl.confdoesn't apply immediately — you mustwsl --terminate <distro>(orwsl --shutdown) and start the distro again. A plainexitand re-launch is not enough; the init process has to restart. .wslconfigchanges ignored — same fix at the VM level:wsl --shutdown, then start a distro to bring the utility VM back up with the new config.--unregisterdeletes data permanently — there is no recycle bin and no undo. Always--exportfirst if you might want the data back.- WSL 1 vs WSL 2 disk performance asymmetry — files under
/home/aliceare fast on WSL 2 and slow on cross-fs/mnt/c. On WSL 1 it's the opposite. Keep working trees on the side that matches your distro version. - VM RAM grows and never shrinks — that's by design; the kernel grabs memory and only releases on
wsl --shutdown. Configure amemory=cap in.wslconfigfor predictability. - Default user resets to
rootafter--import— imported distros don't know about your/etc/wsl.conf [user] default=until you re-create the user and re-edit the file. Use<distro> config --default-user alicedevfor Ubuntu-family distros. wsl --updaterequires the Store app — on builds older than Windows 11 23H2 you may need to switch from the in-box WSL to the Store version (wsl --update) to get newer features.- Network changes need
wsl --shutdown— switchingnetworkingModebetweennatandmirroredwon't take effect from a running VM. - Forgetting
--—wsl -d Ubuntu ls -lamostly works, but flags meant forlscan be eaten bywsl.exe. The explicit--separator removes ambiguity:wsl -d Ubuntu -- ls -la. - Antivirus scanning
ext4.vhdx— some AV products lock the file and break WSL startup. Exclude the per-distroLocalStatedirectory from real-time scanning.
Real-world recipes
Clone a distro to experiment safely
Take a working distro, export it, and re-import as a separate one so you can wreck the clone without losing your daily driver.
$src = "Ubuntu-22.04"
$clone = "Ubuntu-22.04-Sandbox"
$tar = "D:\backups\$src-$(Get-Date -f yyyyMMdd).tar"
$folder = "D:\WSL\$clone"
# 1. Snapshot the source
wsl --export $src $tar
# 2. Import as a new distro (note: NOT the same Path)
New-Item -ItemType Directory $folder -Force | Out-Null
wsl --import $clone $folder $tar --version 2
# 3. Start it as your user (set the same default user as the source)
wsl -d $clone -u root -- bash -c 'usermod -aG sudo alicedev || useradd -m -s /bin/bash -G sudo alicedev'
wsl -d $clone -u root -- bash -c 'printf "[user]\ndefault=alicedev\n" > /etc/wsl.conf'
# 4. Bounce so /etc/wsl.conf is picked up
wsl --terminate $clone
# 5. Verify
wsl -d $clone -- whoami
wsl --list --verbose
Output:
alicedev
NAME STATE VERSION
* Ubuntu-22.04 Stopped 2
Ubuntu-22.04-Sandbox Running 2
Spin up a Docker-friendly distro from scratch
Build a minimal WSL distro from a container image without using the Microsoft Store. Useful when you want full reproducibility or a stripped-down base.
# 1. Grab a base image as a tarball
docker pull debian:bookworm-slim
$cid = docker create debian:bookworm-slim
docker export $cid -o D:\WSL\debian-base.tar
docker rm $cid
# 2. Import it as a new distro
wsl --import DebianLab D:\WSL\debianlab D:\WSL\debian-base.tar --version 2
# 3. Bootstrap a user inside it
wsl -d DebianLab -u root -- bash -c @"
apt-get update
apt-get install -y sudo curl ca-certificates
useradd -m -s /bin/bash -G sudo alicedev
echo 'alicedev ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/alicedev
printf '[user]\ndefault=alicedev\n[boot]\nsystemd=true\n' > /etc/wsl.conf
"@
# 4. Restart so wsl.conf applies
wsl --terminate DebianLab
wsl -d DebianLab -- bash -c 'whoami; cat /etc/os-release | head -2'
Output:
alicedev
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
Move WSL to a faster drive to free up C:
Default WSL distros land on the system drive. Move them to a faster or roomier drive (e.g. D:\WSL\) without re-installing.
$distro = "Ubuntu-22.04"
$dest = "D:\WSL\$distro"
$tar = "D:\backups\$distro-move-$(Get-Date -f yyyyMMdd).tar"
# 1. Snapshot
wsl --export $distro $tar
# 2. Remove the C:-resident copy
wsl --unregister $distro
# 3. Re-import on D:
New-Item -ItemType Directory $dest -Force | Out-Null
wsl --import $distro $dest $tar --version 2
# 4. Re-pin as default and reset the default user
wsl --set-default $distro
wsl -d $distro -u root -- bash -c 'printf "[user]\ndefault=alicedev\n" > /etc/wsl.conf'
wsl --terminate $distro
# 5. Confirm the new disk location
$key = (Get-ChildItem 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss' |
Where-Object { (Get-ItemProperty $_.PSPath).DistributionName -eq $distro }).PSChildName
(Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss\$key").BasePath
Output:
D:\WSL\Ubuntu-22.04
Audit installed distros and disk usage
Produce a one-shot report of every installed distro, its WSL version, default user, and VHDX size — handy before deciding which experiments to clean up.
$rows = foreach ($key in Get-ChildItem 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss') {
$props = Get-ItemProperty $key.PSPath
if (-not $props.DistributionName) { continue }
$vhd = Join-Path $props.BasePath 'ext4.vhdx'
$sizeGB = if (Test-Path $vhd) { [Math]::Round((Get-Item $vhd).Length/1GB, 2) } else { $null }
[pscustomobject]@{
Name = $props.DistributionName
Version = $props.Version
DefaultUser = $props.DefaultUid
BasePath = $props.BasePath
VhdxSizeGB = $sizeGB
}
}
$rows | Sort-Object VhdxSizeGB -Descending | Format-Table -AutoSize
Output:
Name Version DefaultUser BasePath VhdxSizeGB
---- ------- ----------- -------- ----------
Ubuntu-22.04 2 1000 D:\WSL\Ubuntu-22.04 24.31
Ubuntu-22.04-Sandbox 2 1000 D:\WSL\Ubuntu-22.04-Sandbox 18.06
DebianLab 2 1000 D:\WSL\debianlab 2.41
Alpine 2 0 C:\Users\alicedev\AppData\Local\Packages\…\LocalState 0.18