Documentation
¶
Overview ¶
Package networking — WSL2 detection + .wslconfig auto-configuration for LAN peer discovery.
The WSL2 NAT layer between the Windows host and the Linux guest drops cross-host UDP multicast on 224.0.0.251:5353, so two clawtool daemons on the same LAN (one in WSL2, one on another device) cannot find each other via mDNS — even though both are dutifully announcing. Microsoft's supported fix is mirrored networking mode: setting `networkingMode=mirrored` under [wsl2] in `%USERPROFILE%\.wslconfig` makes WSL2 share the host's network interfaces directly. No NAT, no multicast bridge, no portproxy / netsh recipes. Requires Windows 11 22H2 (build 22621) or later AND WSL >= 2.0.0; older Windows versions surface a clear "unsupported" result with fallback recommendations.
This package is platform-neutral. `Detect()` returns InWSL2=false on macOS / native Linux / Windows-without-WSL, so every caller (the doctor section, the serve auto-hook, the `clawtool networking` subcommands) can call it unconditionally without runtime guards.
Index ¶
Constants ¶
const MinMirroredBuild = 22621
MinMirroredBuild is the Windows build number at which `networkingMode=mirrored` first becomes available. Build 22621 = Windows 11 22H2 (the 2022 H2 feature update). Anything below surfaces as an unsupported result with the Windows-host / Tailscale fallback recommendations.
Variables ¶
This section is empty.
Functions ¶
func WriteWSLConfig ¶
WriteWSLConfig serialises cfg to path via atomic temp+rename. Preserves line endings (CRLF on existing Windows-edited files; CRLF when we're creating the file from scratch — the file lives on the Windows filesystem and tools there expect CRLF).
Types ¶
type Action ¶
type Action string
Action enumerates the outcome of EnsureMirrored.
const ( // ActionNoOp — not running in WSL2; nothing to do. ActionNoOp Action = "no-op" // ActionAlreadyConfigured — .wslconfig already has // networkingMode=mirrored. Idempotent re-runs land here. ActionAlreadyConfigured Action = "already-configured" // ActionUnsupported — Windows 10 or pre-22H2 Windows 11. // Mirrored mode is unavailable; the caller should surface // the fallback recommendations (Windows host install / // Tailscale). ActionUnsupported Action = "unsupported" // ActionWouldEdit — DryRun result; the file would have been // modified with the diff returned in Result.Diff. ActionWouldEdit Action = "would-edit" // ActionConfigured — the file was written. The caller MUST // surface Result.NextStep (the wsl --shutdown command) so // the operator restarts WSL2 into the new mode. ActionConfigured Action = "configured" )
type EnsureOptions ¶
type EnsureOptions struct {
// DryRun: compute the planned change but don't write the
// file. The resulting Result includes a Diff field so the
// caller can preview what would change.
DryRun bool
}
EnsureOptions controls EnsureMirrored.
type Result ¶
type Result struct {
// Action is the outcome enum.
Action Action
// Reason is a short human-readable explanation. Required
// for every action; the caller uses it for the operator-
// facing line.
Reason string
// Diff is the unified diff of the .wslconfig change for
// DryRun + Configured outcomes. Empty for NoOp /
// AlreadyConfigured / Unsupported.
Diff string
// NextStep is the operator-facing follow-up — for the
// Configured outcome, this is the `wsl --shutdown && wsl`
// command. Empty otherwise.
NextStep string
// ConfigPath is the resolved .wslconfig path the action
// targeted (or would have targeted). Empty when InWSL2 was
// false.
ConfigPath string
}
Result reports what EnsureMirrored did + what the operator should do next.
func EnsureMirrored ¶
func EnsureMirrored(state *WSL2State, opts EnsureOptions) (Result, error)
EnsureMirrored applies the auto-config recipe per the algorithm:
- If !state.InWSL2 → ActionNoOp.
- If NetworkingMode already "mirrored" → ActionAlreadyConfigured.
- If !MirroredSupported → ActionUnsupported with fallback text.
- If DryRun → ActionWouldEdit + diff.
- Otherwise: read .wslconfig (create if missing), set [wsl2].networkingMode=mirrored, atomic-write, return ActionConfigured with the wsl --shutdown next step.
type WSL2State ¶
type WSL2State struct {
// InWSL2 is true when /proc/version contains "WSL2" — the
// canonical kernel-side marker for the WSL2 distro. Native
// Linux + WSL1 + macOS + Windows-without-WSL all surface
// false; the rest of the struct is then meaningless and the
// caller should treat the WSL2 fix as a no-op.
InWSL2 bool
// WindowsBuild is the major build number from
// `cmd.exe /c ver` (e.g. 19045 for Windows 10 22H2 or 22631
// for Windows 11 23H2). Zero when the probe failed.
WindowsBuild int
// WSLVersion is the version string from `wsl.exe --version`
// (e.g. "2.7.3"). Empty when wsl.exe isn't reachable from
// inside the distro (very old WSL where --version is
// missing).
WSLVersion string
// WindowsUser is the host-side $env:USERNAME read via
// powershell.exe. Used to resolve the .wslconfig path
// (`/mnt/c/Users/<user>/.wslconfig`). Empty when the probe
// failed; in that case WSLConfigPath is also empty and
// EnsureMirrored surfaces a clear error.
WindowsUser string
// WSLConfigPath is the resolved POSIX path the Linux guest
// uses to read / write the Windows-side .wslconfig. Empty
// when WindowsUser wasn't resolvable.
WSLConfigPath string
// NetworkingMode is the current value of [wsl2].networkingMode
// in .wslconfig. Empty string means "key not present" — WSL2
// then uses the default NAT mode. Known values: "nat",
// "mirrored", "bridged", "none". We don't validate the value
// strictly; an unknown mode is preserved verbatim through
// reads + writes.
NetworkingMode string
// MirroredSupported is true when WindowsBuild >=
// MinMirroredBuild. WSL version isn't a hard gate — any WSL
// 2.x shipping with Windows 11 22H2 supports mirrored mode;
// the version field is informational.
MirroredSupported bool
}
WSL2State is the snapshot the auto-config path keys off. Every field is read-only — callers that want to flip the networking mode call EnsureMirrored, which re-reads + writes the .wslconfig rather than mutating this struct.
type WSLConfig ¶
type WSLConfig struct {
// contains filtered or unexported fields
}
WSLConfig is an in-memory representation of a Windows `%USERPROFILE%\.wslconfig` file. The file is INI-ish, not strict TOML: `[section]` headers and `key=value` lines, comments with `#` or `;`. We preserve unrelated sections + key order on write so a user who set `[experimental] sparseVhd=true` doesn't see it silently rewritten or lost.
func ReadWSLConfig ¶
ReadWSLConfig parses a .wslconfig from disk. Returns an empty (but non-nil) config when the file doesn't exist — the caller can SetNetworkingMode + WriteWSLConfig to create it from scratch.
func (*WSLConfig) Bytes ¶
Bytes renders the config back to the on-disk format. Section + key order from the original file is preserved; new keys append to their section in insertion order.
func (*WSLConfig) NetworkingMode ¶
NetworkingMode returns the current value of [wsl2].networkingMode. Empty string when the key isn't set (WSL2 then runs in default NAT mode).
func (*WSLConfig) SetNetworkingMode ¶
SetNetworkingMode writes the value under [wsl2]. Creates the section if missing. Empty value removes the key.