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:

VersionReleasedHighlights
2.7.7 (pre-release)2026-05-19Bumps bundled Microsoft.WSL to 1.0.73.2
2.7.5 (pre-release)2026-05-15Kernel 6.18.26.1 (was 6.6 LTS); fixes VHD permissions for user-supplied volumes
2.7.3 (stable)2026-04-25Settings UI tracks pending changes; ARM64 test-distribution support; IPv6 support for mirrored-mode networking
2.7.12026-03-24Security 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/c access. 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=mirrored in .wslconfig), and DNS tunneling is now an option to route Linux DNS queries through the Windows resolver.
  • wsl --update is the right way to take these — it pulls the latest packaged Microsoft.WSL from the Microsoft Store regardless of how you originally installed.
powershell
wsl --update
wsl --version

Output:

text
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.

powershell
# 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):

text
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.

powershell
wsl.exe [Argument] [Options...]
wsl.exe -d <Distribution> [-u <User>] [-- <command> [args...]]

Output: (none — exits 0 on success)

Essential options

OptionMeaning
--install [-d <Distro>]Install WSL and (optionally) a specific distro
--list, -lList installed distros (--verbose, --quiet, --all, --running)
--list --onlineShow distros available from the Microsoft Store catalogue
--set-default <Distro>, -sSet the default distro
`--set-default-version <12>`
`--set-version <12>`
--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>, -tStop a running distro
--shutdownStop all distros and the WSL VM
--updateUpdate the WSL kernel
--statusShow overall WSL status
--version, -vShow 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, -eExecute 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.

powershell
# 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):

text
  NAME              STATE           VERSION
* Ubuntu-22.04      Running         2
  Ubuntu-20.04      Stopped         2
  Debian            Stopped         2
  Alpine            Stopped         1

Output (wsl --list --online):

text
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.

powershell
# 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):

text
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):

text
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.

powershell
# 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):

text
The operation completed successfully.

Output (wsl -d Debian -- cat /etc/os-release):

text
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.

powershell
# 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):

text
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.

powershell
# 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):

text
The operation completed successfully.

Output (wsl --list --running afterwards):

text
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.

powershell
# 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):

text
Export in progress, this may take a few minutes.
The operation completed successfully.

Output (wsl --list --verbose after import):

text
  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.

powershell
# Tear down a distro completely
wsl --unregister Ubuntu-Restored

# Verify it's gone
wsl --list --verbose

Output:

text
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.

bash
# /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)

powershell
# 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):

text
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.

powershell
# Create or edit .wslconfig
notepad "$env:USERPROFILE\.wslconfig"

Output: (none — opens Notepad on the file)

ini
# 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)

powershell
# 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):

text
               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):

text
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.

bash
# 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)

powershell
# Verify WSLg is enabled (Windows side)
wsl --version

Output (wsl --version):

text
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.

powershell
# 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):

text
C:\Users\alicedev\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu22.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx

Common pitfalls

  1. Editing wsl.conf doesn't apply immediately — you must wsl --terminate <distro> (or wsl --shutdown) and start the distro again. A plain exit and re-launch is not enough; the init process has to restart.
  2. .wslconfig changes ignored — same fix at the VM level: wsl --shutdown, then start a distro to bring the utility VM back up with the new config.
  3. --unregister deletes data permanently — there is no recycle bin and no undo. Always --export first if you might want the data back.
  4. WSL 1 vs WSL 2 disk performance asymmetry — files under /home/alice are 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.
  5. VM RAM grows and never shrinks — that's by design; the kernel grabs memory and only releases on wsl --shutdown. Configure a memory= cap in .wslconfig for predictability.
  6. Default user resets to root after --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 alicedev for Ubuntu-family distros.
  7. wsl --update requires 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.
  8. Network changes need wsl --shutdown — switching networkingMode between nat and mirrored won't take effect from a running VM.
  9. Forgetting --wsl -d Ubuntu ls -la mostly works, but flags meant for ls can be eaten by wsl.exe. The explicit -- separator removes ambiguity: wsl -d Ubuntu -- ls -la.
  10. Antivirus scanning ext4.vhdx — some AV products lock the file and break WSL startup. Exclude the per-distro LocalState directory 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.

powershell
$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:

text
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.

powershell
# 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:

text
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.

powershell
$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:

text
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.

powershell
$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:

text
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

Sources