I would like to identify when Emacs is running on WSL (Windows Subsystem for Linux).
Normally I use system-type variable to check if Emacs is on Linux, Windows or MacOS X.
Though in this case it returns gnu/linux:

system-type is a variable defined in ‘C source code’.
Its value is ‘gnu/linux’

The value is a symbol indicating the type of operating system you are using.
Special values:
  ‘gnu’          compiled for a GNU Hurd system.
  ‘gnu/linux’    compiled for a GNU/Linux system.
  ‘gnu/kfreebsd’ compiled for a GNU system with a FreeBSD kernel.
  ‘darwin’       compiled for Darwin (GNU-Darwin, macOS, ...).
  ‘ms-dos’       compiled as an MS-DOS application.
  ‘windows-nt’   compiled as a native W32 application.
  ‘cygwin’       compiled using the Cygwin library.
Anything else (in Emacs 26, the possibilities are: aix, berkeley-unix,
hpux, usg-unix-v) indicates some sort of Unix system.

Which is what it is expected, though...
I want to add a specific check to use the Windows native browser, not the one on WSL.
I currently do that setting:

(setq browse-url-browser-function 'my-browse-url-function)

But I only want to do this in WSL, not in real Linux.
Is there a way to do it?


3 Answers 3


You could also do (string-match-p "Microsoft" (shell-command-to-string "uname -a"))

Likely in your my-browse-url-function you're probably depending on a Windows specific path to exist. You could just check that it exists and is executable with file-executable-p like the following code does. However, this may not be enough if you dual boot and mount the windows C: drive to the same mount point.

;; setup browser function when running in WSL
(defconst powershell-exe "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe")

(when (file-executable-p powershell-exe)
  (defun my\wsl-browse-url (url &optional _new-window)
    "Opens link via powershell.exe"
    (interactive (browse-url-interactive-arg "URL: "))
    (let ((quotedUrl (format "start '%s'" url)))
      (apply 'call-process powershell-exe
             nil 0 nil (list "-Command" quotedUrl))))

  (setq-default browse-url-browser-function 'my\wsl-browse-url))

I just happened to notice this while looking for a an already implemented wsl-browse-url (thanks!), so will offer one other option:

(when (string-match "-[Mm]icrosoft" operating-system-release)
  ;; WSL: WSL1 has "-Microsoft", WSL2 has "-microsoft-standard"

It looks like that works on both my Debian WLinux WSL 2 environments.

  • This one is available without further system calls. Nice!
    – Tobias
    Commented Feb 4, 2020 at 16:00
  • Where is that wsl-browse-url function? I just made my own modifications to open native chrome.exe on WSL. which it might have problems in some cases, though I am happy with it.
    – nephewtom
    Commented Feb 4, 2020 at 18:28
  • Note operating-system-release has been made obsolete in 28.1 - in the event it is removed without a viable replacement, we can fallback to the response from shell-command on which wsl.exe which should be \mnt\c\Windows\system32\wsl.exe on Win 11 (I don't have a Win 10 machine to test with at the moment.)
    – ocodo
    Commented Jun 10 at 10:42

I would check for an environment variable using getenv. You may want to check what variables are available in your typical WSL shell, but one option would be to check for a Windows-specific PATH entry, perhaps:

(string-match-p "Windows" (getenv "PATH"))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.