enclave.exe is a launcher, not a native port. It forwards every argument it is
given to the Linux enclave binary inside a WSL2 distribution and returns that
binary's exit code. It parses no arguments of its own, so enclave.exe --help,
enclave.exe ps --json, and enclave.exe --tool codex -- -p "…" all behave
exactly as they do on Linux.
There is no native Windows implementation and none is planned. Enclave needs a
Linux container runtime and Linux path semantics; the launcher exists so the
enclave command works from a Windows shell, not to remove that requirement.
-
Install WSL2 and a distribution:
wsl --install -d Ubuntu-24.04
-
Make Docker available inside the distribution, either through Docker Desktop's WSL integration or by installing Docker Engine in the distribution itself. See the requirements.
-
Install the Linux
enclavebuild inside the distribution — the.debor theenclave-linux-amd64/enclave-linux-arm64binary from the rolling release. This is the part that does the work. -
Install the launcher on Windows, with Scoop:
scoop install https://github.com/eclipse-enclave/enclave/releases/download/rolling/enclave.json
Or download
enclave-windows-amd64.zip(enclave-windows-arm64.zipon arm64), verify it againstchecksums.txt, and put the extractedenclave.exeon yourPATH.
Steps 3 and 4 are both required. Installing only the launcher gives you a command that reports that enclave is not installed in the distribution.
winget is not supported: it needs a pull request into microsoft/winget-pkgs
per release, which does not fit a rolling release.
Enclave operates on the project in the current directory, so the launcher derives the distribution from that directory. A distribution can only see its own filesystem, which is why nothing else could work.
| Current directory | Result |
|---|---|
\\wsl.localhost\Ubuntu\home\you\project (or \\wsl$\…) |
Runs in Ubuntu at /home/you/project. This is the intended path. |
A drive letter mapping a WSL share, e.g. Z:\ → \\wsl.localhost\Ubuntu\home\you\project |
Resolved back to the share and treated as the row above. |
C:\Users\you\project |
Refused. With ENCLAVE_WSL_ALLOW_WINDOWS_PATH=1: runs at /mnt/c/Users/you/project in ENCLAVE_WSL_DISTRO or the WSL default distribution. |
\\server\share\… |
Refused. A network share has no path inside a distribution. |
| A drive letter mapping anything else | Refused, and the error names what the drive points at. |
Any of the above reached through a .. component |
Refused. A .. above a distribution root names a directory in a different distribution, so it is not resolved. |
PowerShell supports a \\wsl.localhost\… path as its current location, so the
first row is reachable there directly. cmd.exe cannot hold a UNC working
directory, so pushd \\wsl.localhost\Ubuntu\home\you\project assigns a free
drive letter instead. That is the second row: the launcher asks Windows what the
letter maps to and, when the answer is a WSL share, carries on as if you had
given it the share path. A letter mapping a real file server is still refused,
because no path inside a distribution names those files and guessing one would
bind-mount the wrong directory.
If the letter is mapped below the distribution root, or the working directory
sits deeper than the mapping, the remainder is appended — a Z: mapped to
/home/you/project makes Z:\src mean /home/you/project/src.
Windows drive paths are refused by default because every file access under
/mnt/c crosses the WSL interop layer. That is slow enough to matter for a
repository an agent is actively reading and writing. Keeping the project in the
distribution's own filesystem, for example under ~/, is the fix;
ENCLAVE_WSL_ALLOW_WINDOWS_PATH=1 is the escape hatch when it is not.
If ENCLAVE_WSL_DISTRO names a different distribution than the current directory
lives in, the directory wins and the launcher warns. The other distribution
cannot reach those files.
The launcher reads these on the Windows side. They are not forwarded into the distribution.
| Variable | Effect |
|---|---|
ENCLAVE_WSL_DISTRO |
Distribution to use for a Windows drive path. Ignored, with a warning, when the current directory already names one. |
ENCLAVE_WSL_ALLOW_WINDOWS_PATH |
Set to 1 to accept a Windows drive path and mount it through /mnt/<letter>. |
ENCLAVE_WSL_FORWARD_ENV |
Comma-separated list of extra variables to forward into the distribution. |
WSL only passes variables named in WSLENV, so nothing from your Windows shell
reaches the distribution by default. The launcher forwards:
- every
ENCLAVE_*variable, except the three above andENCLAVE_HOME(whose value is a Windows path that the Linux binary cannot use); - anything named in
ENCLAVE_WSL_FORWARD_ENV, which overrides those exclusions.
Each entry in ENCLAVE_WSL_FORWARD_ENV may carry a WSLENV flag suffix — /p
to translate a single path, /l a path list, /u and /w to restrict the
direction:
$env:ENCLAVE_WSL_FORWARD_ENV = "ANTHROPIC_API_KEY,MY_SCRATCH_DIR/p"A WSLENV you set yourself is preserved; the launcher appends to it and your
flags win for a name you already listed.
Credentials are worth being explicit about: an ANTHROPIC_API_KEY set in
PowerShell does not cross into the distribution unless you name it. The
normal path is to configure credentials inside the distribution — log in from
inside the container on the first run, or use
~/.local/state/enclave/secrets/global.env there. See
Authentication & Secrets.
- Standard input, output, and error are inherited directly rather than piped, so
the agent — and
docker attachunder it — gets a real terminal. The launcher does no terminal emulation. - Ctrl-C is forwarded by
wsl.exeto the child, which owns the decision about what to do with it. The launcher deliberately ignores it so it cannot exit before its child. - The child's exit code is propagated unchanged.
- A launcher-level failure — no WSL2, an unusable working directory, no
enclavein the distribution — exits 125, following Docker's convention for "the launcher failed, not the program". Messages the launcher produces itself are prefixedenclave (windows launcher):, so they are never mistaken for enclave's own output. The one exception is the--cdfallback below, where the shell inside the distribution reports an unreachable directory in its own words and exits 125.
make install puts enclave in ~/.local/bin, which is only on PATH via
~/.profile, and a non-login shell does not read that file. So the launcher
resolves the path first and then executes it:
wsl.exe [-d <distro>] --cd / -e /bin/sh -lc '<fixed probe>', a login shell that triescommand -v enclaveand then~/.local/bin/enclave,/usr/local/bin/enclave,/usr/bin/enclave. The probe interpolates nothing. It prints its answer behind anenclave-bin=marker, so a shell profile that writes to standard output is not mistaken for the path. Passing--cdhere is also how support for it is detected, at no extra cost.wsl.exe [-d <distro>] --cd <path> -e <absolute path> <your arguments…>, which runs the binary directly with no shell to re-parse anything.
That costs one extra round trip, roughly 100–300 ms on a cold distribution. The
result is not cached. On a wsl.exe old enough to lack --cd, the launcher
retries and changes directory through a shell instead, still passing your
arguments as positional parameters so they are never re-split.
-e runs the binary directly, which is what keeps a shell from re-parsing your
arguments, but it also means the distribution's /etc/profile,
/etc/profile.d/*, ~/.profile, and ~/.bashrc do not run. Enclave gets WSL's
default environment instead of the one an interactive WSL session has.
That is invisible for a normal setup, where docker is on the default PATH.
It is not invisible if your shell profile is what makes Docker reachable —
rootless Docker's install instructions, for example, put
export DOCKER_HOST=unix:///run/user/$UID/docker.sock in ~/.bashrc. Enclave
would then report that it cannot reach the Docker daemon, from a distribution
where running enclave in a terminal works.
Configure such variables so they apply outside an interactive shell —
/etc/environment, or a systemd user environment — rather than in a shell
profile. Anything set on the Windows side can be carried across with
ENCLAVE_WSL_FORWARD_ENV.
- No native Windows support.
- The session does not inherit the distribution's shell profile; see above.
- The launcher installs nothing: not WSL2, not a distribution, not Docker, not
the Linux
enclavebuild. - No diagnostic command; failures are reported inline.
- Argument passing is verified against a reimplementation of Windows' own
command-line parsing in CI, and against a real
wsl.exeby a manual pre-release gate (see DEV.md). GitHub-hosted Windows runners have no WSL2, so the empirical half cannot run there.