skip to content

wsl — Managing Linux Distros from the wsl.exe CLI

Install, list, export, import, configure, and clone WSL distributions using the wsl.exe command on Windows 10 and 11.

16 min read 45 snippets deep dive

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

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.

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

  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.

$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

Sources#