Metadata-Version: 2.4
Name: wslenv
Version: 0.2.0
Summary: Script to investigate environment variables useful in WSL if missing
Author: Michael Dubner
Author-email: pywebmail@list.ru
Requires-Python: >=3.12
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Description-Content-Type: text/markdown

# wslenv

`wslenv` is a small helper script intended to populate and print environment variables that are useful when running inside **WSL (Windows Subsystem for Linux)** - especially when those variables are missing.

It detects WSL, prepares distro info, configures interop, and merges the Windows `PATH`. Optionally, it prepares WSLg-related GUI variables.

At the end, it prints shell-ready `export` commands for any variables it had to set.

## Rationale

**Why you need it**
There are situations where you end up inside a WSL distribution without the expected interop variables. For example:

- Log into it via SSH. I.e. you have in your `~/.ssh/config`:
  ```plain
  Host wsldistr-inside-winhost
    ProxyCommand ssh winhost wsl -d wsldistr -u root sshd -i
  ```
- After `sudo -H -i`.

## Installation

If you want it only as a program available in your `PATH`, use `pipx`:

```sh
pipx install wslenv
```

If you want to have development version:

```console
$ git clone https://github.com/pyhedgehog/wslenv.git
$ cd wslenv
$ pipx install -e .
```

## Usage

```console
# wslen --help
usage: wslenv [-h] [--no-gui] [--unset]

Script to investigate environment variables useful in WSL if missing.

options:
  -h, --help            show this help message and exit
  --no-gui, --no-wslg, --plain, -p
                        Skip WSLg variables.
  --unset, -u           Unset WSL/WSLg variables.

Varibles: PATH, WSL_DISTRO_NAME, WSL_INTEROP, WSLENV, *(vars from WSLENV);
WSLg variables: DISPLAY, PULSE_SERVER, WAYLAND_DISPLAY, WSL2_GUI_APPS_ENABLED, XDG_RUNTIME_DIR
```

Typical usage is to evaluate wslenv output in your shell or in your script (i.e. in `~/.profile`:

```sh
eval "$(wslenv)"
```

If you want to skip WSLg variables:

```sh
eval "$(wslenv --no-gui)"
```

If you want to unset WSLg variables (keeping WSL variables):

```sh
eval "$(wslenv --unset --no-gui)"
```

If you want to unset all WSL variables:

```sh
eval "$(wslenv --unset)"
```

## What it sets

### Core WSL variables

- `WSL_INTEROP` - detects the nearest parent WSL interop relay
- `WSL_DISTRO_NAME` - uses `wslpath -w /`
- `WSLENV` - gets Windows `WSLENV` or sets it to empty
- `PATH` - merges Windows `PATH` entries into the Linux `PATH` (avoids duplicates)

Also variables mentioned in WSLENV can be set.

### Optional WSLg variables (GUI apps)

When GUI support is detected and `--no-gui` / `--no-wslg` is not used:

- `WAYLAND_DISPLAY`
- `PULSE_SERVER`
- `XDG_RUNTIME_DIR`
- `DISPLAY`
- `WSL2_GUI_APPS_ENABLED`

## Notes

The script relies on WSL interop utilities:

- `wslpath -m /`
- `wslinfo --msal-proxy-path`
- `cmd.exe /c set`

There are some corner cases:

1. All variables processed by wslenv and wsl itself can has different result.
   Normal wsl startup procedure first sets wsl-specific variables and the processes shell's profile.
   But when you use `eval $(wslenv)` (even in `.bashrc`) you already has initial setup done.
1. Any wsl-specific variable (including mentioned in `$WSLENV`) set by wslenv only if it not set from some other source.
1. `$PATH` and `*/l` variables mentioned in `$WSLENV` processed differently - paths from windows `%Path%` added to `$PATH`,
   but variables from WSLENV defined only if they are not already defined in current environment.

## Roadmap

- Run command in modified environment (like `wslenv -c cmd.exe /c echo %PATH%`).
- Check in fresh `wslc.exe` containers.
- Make OS packages (at least for Alpine and Ubuntu as sane and default WSL distributions).
- Detect WSL kernel version and process corner cases if found.
- Make minimal version - i.e. without python dependencies (shell or compilable - C/Ninja/Rust/codon/...).
- Plugins? No idea what for. :-(

### Help wanted

- Would anyone be willing to help improve this documentation?
- Documentation for using it as a module too. https://github.com/pyhedgehog/wslenv/pulls
- Double-check WSLENV corner-cases in **different versions** of WSL:
  - UPPER/lower chars in variable names. See https://github.com/Microsoft/WSL/issues/8639
  - Special chars in variable names. See https://github.com/Microsoft/WSL/issues/10697
  - Relative paths when converted by `/p` and `/l`. See https://github.com/Microsoft/WSL/issues/5274
  - Non-local paths `\\remote\share\path` in `%PATH%` or `/pl`.
  - WSL distribion specific paths. See https://github.com/microsoft/WSL/issues/3725#issuecomment-5409636503
- Watch for future WSL features related to env processing:
  - Globs (`WSLENV=JAVA*/l` to set all variables starting with `JAVA`). See
  - Append to path-like variables. See https://github.com/Microsoft/WSL/issues/6020
  - Converting variable names. See https://github.com/Microsoft/WSL/issues/5341
  - Forced setting of variables. See https://github.com/Microsoft/WSL/issues/10697
  - Replace `cmd.exe /c set` with better alternative. See https://github.com/Microsoft/WSL/issues/12504
- Maybe you can invent something more? https://github.com/pyhedgehog/wslenv/issues

## Changelog

### 0.2.0 (2026-09-01)

- Support for unsetting variables using `wslenv -u`.
- Import from Windows variables mentioned in inherited or imported `WSLENV`.

### 0.1.0 (2026-07-28)

- Initial release to [github](https://github.com/pyhedgehog/wslenv) and [pypi](https://pypi.org/project/wslenv/).
- Make mypy/pyrefly happy.

### 0.0.0 (2026-07-20)

- Never released.
- First usable code.

