Skip to content
WSL2 Cheat/sheet

Optional extras

Personalise the environment. Nothing here is needed for the rest of the guide to work, and every recipe says how to undo it.

Shell

Switch your shell to zsh#

Optional. Replace bash with zsh plus autosuggestions and syntax highlighting, and keep mise working.

Optional. Bash from the baseline setup works for everything in this guide. Do this if you want history-based suggestions and command highlighting as you type.

When to use it#

You spend most of the day in the terminal and want a more helpful interactive shell. It changes nothing about how projects build or run.

Prerequisites#

Steps#

  1. Install zsh and the two plugins most people want:

    WSLzsh and plugins
    sudo apt install -y zsh zsh-autosuggestions zsh-syntax-highlighting
  2. Create ~/.zshrc with mise activation and the plugins. Syntax highlighting must be the last line:

    File~/.zshrc
    autoload -Uz compinit && compinit -C
    eval "$(~/.local/bin/mise activate zsh)"
    source /usr/share/zsh-autosuggestions/zsh-autosuggestions.zsh
    source /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh   # must be last
  3. Make zsh your login shell, then close and reopen the terminal:

    WSLChange the default shell
    chsh -s "$(which zsh)"

    If zsh shows its first-run menu, press q; your ~/.zshrc already exists.

More tools that plug into ~/.zshrc (fuzzy history, smarter cd, a prompt): A fast prompt and Modern command-line tools.

Verify#

  • echo $SHELL prints /usr/bin/zsh.
  • which node still prints a path under ~/.local/share/mise.
  • Typing the start of a previous command shows the rest in grey; → accepts it.
  • time zsh -i -c exit reports well under 0.2 s.

Troubleshoot#

  • node: command not found after switching: the mise line is missing from ~/.zshrc, or says activate bash. It must say activate zsh.
  • Startup feels slow: comment lines out of ~/.zshrc one at a time and re-run time zsh -i -c exit. compinit without -C and Windows interop lookups are common causes.

Undo#

WSLBack to bash
chsh -s /bin/bash

Reopen the terminal. ~/.zshrc can stay; bash ignores it.

Shell

A fast prompt with Starship#

Optional. A prompt that shows Git branch, runtime versions and command duration, with a Nerd Font so its icons render.

Optional. A plain prompt works fine; this one adds context at a glance.

When to use it#

You want the current Git branch, dirty state, runtime version and how long the last command took, without a slow prompt framework.

Prerequisites#

Steps#

  1. Install a Nerd Font on Windows, for example JetBrainsMono Nerd Font from nerdfonts.com: unzip, select the .ttf files, right-click → Install.

  2. Select it in Windows Terminal (Settings → Ubuntu → Appearance → Font face) and in your editor’s terminal font setting.

  3. Install Starship into your home directory (no sudo needed):

    WSLInstall Starship
    mkdir -p ~/.local/bin
    curl -sS https://starship.rs/install.sh | sh -s -- -b ~/.local/bin
  4. Add the init line after mise activation, then reopen the terminal:

    File~/.zshrc (or ~/.bashrc with: starship init bash)
    eval "$(starship init zsh)"

Verify#

The prompt shows the folder and, inside a Git repo, the branch. Icons render as symbols, not empty boxes. Run sleep 3: the next prompt shows the duration.

Troubleshoot#

  • Boxes or question marks instead of icons: the terminal font is not a Nerd Font. Fonts are chosen on Windows, not in Linux.
  • starship: command not found: ~/.local/bin is not on PATH. Ubuntu adds it at login if the folder exists; open a new terminal after step 3.

Undo#

Remove the starship init line and run rm ~/.local/bin/starship.

Shell

Modern command-line tools#

Optional. fzf, zoxide, direnv, eza, bat, ripgrep, delta, lazygit, atuin and friends, with the init order that keeps zsh fast.

Optional. Each tool is independent; install the ones you’ll use.

When to use it#

You want faster search, fuzzy history, per-project environment variables and nicer diffs in the terminal.

Prerequisites#

  • zsh (the init block below is for zsh; most tools also have bash equivalents).
  • mise from setup step 5, for the tools not packaged in Ubuntu.

Steps#

  1. Tools packaged by Ubuntu:

    WSLFrom apt
    sudo apt install -y fzf zoxide direnv eza bat fd-find ripgrep jq btop tmux git-delta

    eza and git-delta are in Ubuntu 24.04’s repositories; on older releases install them with mise use -g instead.

  2. Tools Ubuntu doesn’t package (or packages old versions of), via mise:

    WSLFrom mise
    mise use -g lazygit atuin dust lazydocker
  3. Wire them into ~/.zshrc. Order matters: keep mise first and syntax highlighting last. Leave out lines for tools you didn’t install.

    File~/.zshrc: init order
    autoload -Uz compinit && compinit -C
    eval "$(~/.local/bin/mise activate zsh)"
    eval "$(starship init zsh)"          # if you use the prompt
    eval "$(direnv hook zsh)"
    source /usr/share/doc/fzf/examples/key-bindings.zsh
    eval "$(atuin init zsh --disable-up-arrow)"
    eval "$(zoxide init zsh --cmd cd)"   # late: after other cd/chpwd hooks
    alias bat=batcat fd=fdfind           # Ubuntu package names
    alias ll="eza -la --git --group-directories-first"
    alias lg=lazygit
    source /usr/share/zsh-autosuggestions/zsh-autosuggestions.zsh
    source /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh   # must be last
  4. Use delta for Git diffs (only after git-delta is installed, or Git can’t show diffs):

    WSLdelta as Git's pager
    git config --global core.pager delta
    git config --global delta.navigate true

What you get#

Keys / commandWhat it does
→ on grey textAccept autosuggestion from history
Ctrl+RFuzzy history search (atuin: folder, exit code, duration)
Ctrl+T / Alt+CFuzzy-pick a file path / jump into a subfolder
cd projzoxide: jump to your most-used folder matching “proj”
.envrc + direnv allowPer-project env vars, loaded on cd in and unloaded on the way out
tmux new -s app / tmux a -t appSessions that survive closing the terminal tab
rg pattern / fd nameFast content and file-name search
lg / lazydockerGit and Docker in a terminal UI
dust -d 2 ~What is using disk space

Verify#

Open a new terminal. Ctrl+R opens a searchable history, ll lists files with Git status, and git diff shows side-by-side colour. time zsh -i -c exit should stay under 0.2 s.

Troubleshoot#

  • command not found: atuin (or another mise tool): mise activation must come before its init line.
  • git diff prints nothing or errors: core.pager is delta but delta isn’t installed. Install it or run git config --global --unset core.pager.
  • Ctrl+R shows fzf instead of atuin: atuin’s init must come after the fzf key bindings.

Undo#

Remove the lines from ~/.zshrc, then uninstall what you no longer want: sudo apt remove <package> for apt tools, mise unuse -g <tool> for mise tools, and git config --global --unset core.pager for delta.

Windows integration

Call Windows apps without the Windows PATH#

Optional. Stop Windows' PATH leaking into Linux for a faster shell and no node/npm mix-ups, then add back only code, Explorer, the clipboard and PowerShell.

Optional. The default (Windows PATH appended) works; this trades a little setup for a faster, more predictable shell.

When to use it#

Command lookup feels slow, or which node sometimes finds the Windows install under /mnt/c. Skip this if neither bothers you.

Prerequisites#

  • Know the consequence: with appendWindowsPath=false, code, cursor, explorer.exe and powershell.exe are no longer found until step 2 adds them back. Do both steps together.
  • Editor installed on Windows (Open a WSL project in your editor).

Steps#

  1. Turn the Windows PATH off in /etc/wsl.conf (sudo nano /etc/wsl.conf):

    File/etc/wsl.conf (sudo)
    [interop]
    enabled=true
    appendWindowsPath=false
  2. Add back what you use, in a file both bash and zsh can source:

    File~/.config/shell/common.sh
    _win=/mnt/c/Windows
    _winuser=$(wslpath "$($_win/System32/cmd.exe /c 'echo %USERPROFILE%' 2>/dev/null | tr -d '\r')")
    _apps="$_winuser/AppData/Local/Programs"
    [ -d "$_apps/Microsoft VS Code/bin" ] && export PATH="$PATH:$_apps/Microsoft VS Code/bin"
    [ -d "$_apps/cursor/resources/app/bin" ] && export PATH="$PATH:$_apps/cursor/resources/app/bin"
    
    alias open="$_win/explorer.exe"                 # open .  → Explorer here
    alias clip="$_win/System32/clip.exe"            # echo hi | clip
    alias pwsh="$_win/System32/WindowsPowerShell/v1.0/powershell.exe"
    alias winget="$_winuser/AppData/Local/Microsoft/WindowsApps/winget.exe"
    unset _win _winuser _apps
  3. Source it from your shell’s rc file, then restart WSL from PowerShell with wsl --shutdown:

    WSLLoad it in bash (use ~/.zshrc for zsh)
    mkdir -p ~/.config/shell
    echo 'source ~/.config/shell/common.sh' >> ~/.bashrc

Verify#

  • echo $PATH | tr ':' '\n' | grep -c /mnt/c prints 1 or 2 (only the editor folders), not dozens.
  • code . opens VS Code with WSL: Ubuntu; open . opens Explorer.
  • which node points into ~/.local/share/mise.

Troubleshoot#

  • code: command not found: the install folder differs (system-wide installs live in C:\Program Files\Microsoft VS Code\bin). Adjust the path in common.sh. More: A Windows command is not found.
  • Nothing changed: /etc/wsl.conf is only read at start. Run wsl --shutdown in PowerShell.

Undo#

Set appendWindowsPath=true (or delete the line) in /etc/wsl.conf, remove the source line, and run wsl --shutdown.

Windows integration

Make Windows Terminal open in Linux#

Optional. Make Ubuntu the default Windows Terminal profile, start tabs in your Linux home, and learn the handful of keys worth knowing.

Optional. A convenience for people who open terminals all day.

When to use it#

New terminal tabs open PowerShell, or open Ubuntu in /mnt/c/Users/<you> instead of your Linux home.

Prerequisites#

  • Windows Terminal (included with Windows 11).
  • Ubuntu installed (setup step 1).

Steps#

  1. Windows Terminal → Ctrl+, → Startup → Default profile: Ubuntu.

  2. Profiles → Ubuntu → Command line:

    PowerShellUbuntu profile command line
    wsl.exe -d Ubuntu --cd ~
  3. Optional: Appearance → Font face to a Nerd Font if you use a prompt with icons.

  4. Save.

Keys worth knowing#

KeysWhat it does
Ctrl+Shift+TNew tab (default profile)
Ctrl+Shift+SpaceProfile menu
Alt+Shift+DSplit pane
Alt+arrowsMove between panes
Ctrl+,Settings

Verify#

Ctrl+Shift+T opens Ubuntu, and pwd prints /home/<you>.

Undo#

Set Default profile back to Windows PowerShell and clear the custom command line (the profile’s default is wsl.exe -d Ubuntu).

Conveniences

Small conveniences#

Optional. Clipboard, path conversion, opening URLs and Explorer from Linux, Linux GUI apps, public URLs, throwaway distros and other small time-savers.

Optional. Each item stands alone; none of them is needed elsewhere in this guide.

Windows from Linux#

  • Open Explorer here: explorer.exe . opens the current Linux folder in Windows.
  • Clipboard both ways: cat key.pub | clip.exe. In tmux copy mode, pipe the selection to clip.exe.
  • Translate paths: wslpath -w . gives a Windows path; wslpath 'C:\Users' goes the other way.
  • Open URLs in the Windows browser: install wslu and set BROWSER=wslview, so CLI logins (gh auth login, npm login) open your Windows browser.
WSLwslview as the default browser
sudo apt install -y wslu
echo 'export BROWSER=wslview' >> ~/.bashrc      # or ~/.zshrc

These need Windows interop, which is on by default. If you turned off the Windows PATH, use the full paths or the aliases from Call Windows apps without the Windows PATH.

Linux from Windows#

  • Run a Linux command from PowerShell: wsl -e htop, wsl --cd ~ -e pnpm dev, or simply wsl ls -la.
  • Linux GUI apps: WSLg runs apps like gitk or meld as normal Windows windows (sudo apt install -y gitk meld).

Development#

  • A public URL in one line: cloudflared tunnel --url http://localhost:3000 gives a temporary HTTPS address for webhooks and demos. Install with mise use -g cloudflared. Anyone with the URL reaches your dev server, so stop it when you’re done.
  • Throwaway distros: wsl --install -d Debian, or import a backup under a new name (Back up and restore your WSL distro), to try risky setups away from your main environment. wsl --unregister Debian deletes it and everything in it.
  • Containers in a terminal UI: lazydocker shows logs, stats and restarts with single keys (install it).

Shell history#

  • Keep secrets out of history: start a line with a space. zsh (with setopt HIST_IGNORE_SPACE) and atuin skip it. atuin search --delete "text" removes past entries.
  • See what you type most: atuin stats.

Windows desktop#

  • Snap windows: PowerToys FancyZones keeps terminal, editor and browser in fixed zones. PowerToys Command Palette opens on Win+Alt+Space.