wsl-host-start

module
v1.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 28, 2026 License: MIT

README

wstart

CI

Alpha — This project is under active development. APIs and config formats may change. Use at your own risk.

Launch Windows programs from WSL — the way start works on Windows.

Why

wslu/wslview was archived in March 2025 and Ubuntu is dropping it from future releases. The common cmd.exe /C start alias fails on UNC paths, has no elevation support, and requires manual path translation.

wstart fills this gap with two small Go binaries that give you full ShellExecuteEx access from any WSL shell:

  • Open files with their default Windows application
  • Launch programs with admin privileges (UAC elevation)
  • Use any ShellExecuteEx verb — open, edit, print, runas, explore, properties
  • Automatic path translation between WSL and Windows, including subst and network drive aliases
  • Wait for launched processes and capture exit codes

That last point matters for tools like Perforce where the workspace root may live on a subst'd drive letter. wstart does longest-prefix alias matching so p4 sees the drive letter it expects.

Quick Start

wstart document.pdf              # Open in default PDF viewer
wstart .                         # Open current directory in Explorer
wstart https://google.com        # Open URL in default browser
wstart -verb runas cmd.exe       # Launch elevated command prompt
wstart -verb print report.docx   # Print a document
wstart -wait installer.exe       # Wait for process to exit

Installation

scoop bucket add wstart https://github.com/sverrirab/scoop-bucket
scoop install wstart

Then complete the setup:

wstart-host.exe --install

This requests administrator privileges to copy binaries to C:\Program Files\wstart\, create default configs, and print WSL setup instructions. Installing to Program Files ensures WSL processes cannot modify the host binary or config files.

Follow the printed instructions to create a symlink in your WSL session and add it to your PATH.

Manual install / from source

See docs/manual-install.md for installing from a GitHub release zip or building from source.

Upgrading
scoop update wstart
wstart-host.exe --install

Or download the new release and run --install again. Existing config and allowlist files are preserved.

Prerequisites
  • WSL (1 or 2) with interop enabled (the default)
  • Go 1.24+ (only needed when building from source)

Usage

Flags
  -verb string     ShellExecuteEx verb (default "open")
  -dir string      Working directory (WSL or Windows path)
  -wait            Wait for the launched process to exit
  -min             Start minimized
  -max             Start maximized
  -hidden          Start hidden
  -dry-run         Print translated command without executing
  -verbose         Print diagnostic info
  -refresh-drives  Refresh drive cache and exit
  -check-config    Show active configuration diagnostics
  -version         Print version
Host helper flags

The Windows helper (wstart-host.exe) has additional management flags:

  --install        Install binaries and create default configs
  --check-config   Print configuration diagnostics (config, allowlist, signing, drives)
  --sign-config    Re-sign config files after editing
  --verbose        Show extra detail in check-config output

Configuration

All configuration lives on the Windows host in C:\Program Files\wstart\. wstart works out of the box for common cases. For advanced setups (subst drives, Perforce, env forwarding), edit config.toml.

Important: After editing any config file, re-sign it from PowerShell:

wstart-host.exe --sign-config

Config files are signed with an HMAC key stored in the Windows Registry to prevent tampering from WSL. If signatures are invalid, wstart will refuse to launch programs.

config.toml
[drives]
# Manual drive alias overrides (supplements auto-detection)
[drives.aliases]
P = "C:\\dev\\workspace"
Z = "\\\\server\\share"

# Use aliased drive letters when translating paths (default: true)
prefer_aliases = true

# Query the host for subst/network drives automatically (default: true)
auto_detect = true

[env]
# Environment variables to forward to Windows processes
forward = ["P4PORT", "P4CLIENT", "P4USER", "P4CONFIG"]

# Variables that are NEVER forwarded (default includes P4PASSWD, P4TICKETS, P4TRUST)
block = ["P4PASSWD", "P4TICKETS", "P4TRUST"]

[defaults]
verb = "open"
show = "normal"  # normal | min | max | hidden
Drive alias resolution

When prefer_aliases = true, wstart applies longest-prefix matching to replace physical paths with aliased drive letters. This is critical for Perforce:

WSL cwd:    /mnt/c/dev/workspace/project
Subst:      P: → C:\dev\workspace
Result:     P:\project            ← matches p4 workspace root

Run wstart -refresh-drives to update the cached drive mappings.

Diagnostics

Check your active configuration from either side:

# From WSL
wstart -check-config

# From PowerShell (more detail — includes drives and signing status)
wstart-host.exe --check-config
wstart-host.exe --check-config --verbose

Security

Allowlist

The Windows helper supports an optional allowlist that restricts which programs and subcommands can be executed. Edit allowlist.toml in C:\Program Files\wstart\:

# Only these programs can be launched via wstart.
# Delete this file to allow all programs.

[[allow]]
program = "p4"
commands = ["info", "sync", "edit", "submit", "diff", "opened"]

[[allow]]
program = "notepad.exe"

[[allow]]
program = "explorer.exe"

[[allow]]
program = "code"

If the file is absent, all programs are allowed. When present, the helper checks each request before executing:

  • Program matching: case-insensitive, with or without .exe, works with full paths
  • Subcommand matching: finds the first positional argument, skipping flags
  • Denied requests: return SE_ERR_ACCESSDENIED with a descriptive error message
Deny list (hardcoded)

The following programs are always blocked regardless of allowlist configuration, because they are shell/exec bypass vectors:

cmd, powershell, pwsh, wscript, cscript, mshta, rundll32, regsvr32, bash

This deny list is compiled into the binary and cannot be overridden by editing config files.

Install directory protection

wstart installs to C:\Program Files\wstart\, which requires administrator privileges to modify. This means:

  • A WSL process (running as a normal user) cannot replace the host binary, config files, or signature files
  • --install and --sign-config automatically request UAC elevation
  • Read-only operations (--launch, --exec, --check-config) do not require elevation
Config signing

Config files (config.toml, allowlist.toml) are additionally protected by HMAC-SHA256 signatures:

  • A random signing key is stored in the Windows Registry (HKCU\Software\wstart), which is not accessible from the WSL filesystem
  • Each config file has a companion .sig file containing its signature
  • The host binary verifies signatures on every launch — tampered files are rejected
  • After legitimate edits, re-sign with wstart-host.exe --sign-config (requires admin)

Together with the Program Files location, this provides defense in depth against a compromised WSL process.

Using Perforce from WSL

With wstart configured, you can run Perforce commands from your WSL shell with correct drive mapping:

# Sync your workspace (cwd is translated to the subst drive)
wstart -wait p4 sync

# Edit a file
wstart -wait p4 edit //depot/main/src/file.cpp

# Check what files you have open
wstart -wait p4 opened

# Submit a changelist
wstart -wait p4 submit -d "Fix buffer overflow"

# Shell alias for convenience
alias p4='wstart -wait p4'
p4 sync
p4 edit file.cpp

The -wait flag is important for p4 — it makes wstart block until the command finishes so you see the output and get the correct exit code.

Architecture

Two cooperating binaries connected via JSON over stdin/stdout:

WSL (Linux)                        Windows Host
┌──────────────┐   LaunchRequest   ┌───────────────────┐
│  wstart      │ ────────────────► │  wstart-host.exe  │
│  - parse CLI │   stdin (JSON)    │  - ShellExecuteExW │
│  - translate │ ◄──────────────── │  - drive enumerate │
│    paths     │   stdout (JSON)   │  - exit codes      │
└──────────────┘   LaunchResponse  └───────────────────┘

No daemon, no sockets, no PowerShell. The Windows helper calls Win32 APIs directly for speed and full control.

Development

make build        # Cross-compile both binaries
make test         # Run tests
make clean        # Remove bin/
Project layout
cmd/wstart/          WSL CLI entry point (linux/amd64)
cmd/wstart-host/     Windows helper entry point (windows/amd64)
internal/
  protocol/          Shared JSON request/response types
  allowlist/         Host-side program/subcommand allowlist + deny list
  config/            TOML config loading
  signing/           HMAC-SHA256 config signing (registry key + .sig files)
  install/           Self-installation logic (Windows side)
  pathconv/          Path translation with drive alias resolution
  drivecache/        TTL-based cache of drive enumeration
  interop/           WSL environment detection
  launch/            Orchestration (WSL side)
  drives/            Win32 drive enumeration (Windows side)
  shellexec/         ShellExecuteExW wrapper (Windows side)
Releasing

Releases are built with GoReleaser via GitHub Actions. To create a release:

git tag v0.1.0
git push origin v0.1.0

This triggers the release workflow which cross-compiles both binaries and publishes a zip to GitHub Releases.

CI

Builds and lints are run via GitHub Actions. The workflow lints both platforms separately (GOOS=linux and GOOS=windows), runs tests on platform-independent packages, and cross-compiles both binaries.

License

MIT

Directories

Path Synopsis
cmd
wstart command
wstart is the WSL-side CLI that launches Windows programs via ShellExecuteEx.
wstart is the WSL-side CLI that launches Windows programs via ShellExecuteEx.
wstart-host command
wstart-host is the Windows-side helper binary.
wstart-host is the Windows-side helper binary.
internal
allowlist
Package allowlist enforces a host-side list of allowed programs and subcommands.
Package allowlist enforces a host-side list of allowed programs and subcommands.
config
Package config loads the wstart TOML configuration file.
Package config loads the wstart TOML configuration file.
drivecache
Package drivecache manages a local cache of Windows drive information.
Package drivecache manages a local cache of Windows drive information.
drives
Package drives enumerates Windows drive letters and their types using Win32 APIs.
Package drives enumerates Windows drive letters and their types using Win32 APIs.
elevate
Package elevate provides UAC elevation detection and self-elevation for Windows binaries.
Package elevate provides UAC elevation detection and self-elevation for Windows binaries.
install
Package install handles self-installation of wstart-host.exe and the WSL companion binary to %LOCALAPPDATA%\wstart\.
Package install handles self-installation of wstart-host.exe and the WSL companion binary to %LOCALAPPDATA%\wstart\.
interop
Package interop detects the WSL interop environment.
Package interop detects the WSL interop environment.
launch
Package launch orchestrates the WSL-side workflow: detect environment, load config, translate paths, invoke the Windows helper, and return results.
Package launch orchestrates the WSL-side workflow: detect environment, load config, translate paths, invoke the Windows helper, and return results.
pathconv
Package pathconv translates paths between WSL and Windows formats, applying drive alias resolution for subst/network drives.
Package pathconv translates paths between WSL and Windows formats, applying drive alias resolution for subst/network drives.
protocol
Package protocol defines the JSON types shared between the WSL CLI and Windows helper.
Package protocol defines the JSON types shared between the WSL CLI and Windows helper.
shellexec
Package shellexec wraps Windows process execution APIs.
Package shellexec wraps Windows process execution APIs.
signing
Package signing provides HMAC-SHA256 config file signing and verification.
Package signing provides HMAC-SHA256 config file signing and verification.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL