WSL Integration
Unified WSL/Windows file integration in a single tool Version: v4.5.29 | Last updated: 2026-07-11
Table of Contents
Section titled “Table of Contents”- What changed in v4.x?
- The unified
wsltool - Actions at a glance
- Cross-platform path conversion
- Auto-sync via
MCP_WSL_AUTOSYNC(v3.x legacy) - Allowed-paths and security
- Common workflows
- Troubleshooting
What changed in v4.x?
Section titled “What changed in v4.x?”In v3 (≤ 3.13.2) the WSL surface was a fleet of separate tools:
wsl_sync, wsl_status, configure_autosync, autosync_status,
wsl_to_windows_copy, windows_to_wsl_copy, sync_claude_workspace, and
wsl_windows_status. Most were removed during the v4.0.0 consolidation.
In v4.5.x the entire surface lives under one tool: wsl. Four actions
cover every use case, and path conversion is automatic in every read/write/edit
tool (you rarely need to call wsl at all — see
Cross-platform path conversion).
| v3.x tool | v4.5.x replacement |
|---|---|
wsl_status | wsl(action:"status") |
wsl_sync | wsl(action:"sync", ...) |
configure_autosync | wsl(action:"autosync_config", enabled:...) |
autosync_status | wsl(action:"autosync_status") |
wsl_to_windows_copy | wsl(action:"sync") w/ wsl_path+windows_path |
windows_to_wsl_copy | wsl(action:"sync") w/ windows_path+wsl_path |
sync_claude_workspace | wsl(action:"sync", direction:..., filter_pattern:...) |
The unified wsl tool
Section titled “The unified wsl tool”The wsl tool is the single entry point for everything related to WSL/Windows
integration. It accepts an action parameter that selects one of four modes:
// Compact discovery — list the actions:help() // full tool catalogThe four actions (see tools_platform.go for the live source):
action | Purpose |
|---|---|
sync (default) | Workspace sync OR single-file copy WSL↔Windows |
status | Environment + paths + directory status report |
autosync_config | Enable / disable auto-sync on writes and edits |
autosync_status | Read the current auto-sync config + whether it is active |
The handler validates both source and destination paths against
--allowed-paths after conversion, so a caller cannot bridge a write through
a denied directory.
Actions at a glance
Section titled “Actions at a glance”1. wsl(action:"sync") — workspace sync or single-file copy
Section titled “1. wsl(action:"sync") — workspace sync or single-file copy”sync has two modes selected by the parameters supplied:
Workspace sync (when direction is set)
Section titled “Workspace sync (when direction is set)”wsl({ action: "sync", direction: "wsl_to_windows", // wsl_to_windows | windows_to_wsl | bidirectional filter_pattern: "*.go", // optional glob create_dirs: true, // default true dry_run: false // preview without writing})Compact response: OK: 12 files synced, 0 errors
Verbose response lists every synced file and any per-file error (capped at 10 errors to keep responses bounded).
Single-file copy (when wsl_path or windows_path is set)
Section titled “Single-file copy (when wsl_path or windows_path is set)”// WSL → Windows (auto-computes Windows path from wsl_path if missing)wsl({ action: "sync", wsl_path: "/home/user/app.go"})
// Windows → WSLwsl({ action: "sync", windows_path: "C:\\Users\\user\\app.go", wsl_path: "/home/user/app.go" // optional — auto-computed if omitted})Compact response: OK: Copied to C:\Users\user\app.go
The TOCTOU defense runs before every copy — both source and destination are
re-resolved via engine.ResolveAndAuthorize so a symlink cannot redirect the
copy outside --allowed-paths.
2. wsl(action:"status") — environment report
Section titled “2. wsl(action:"status") — environment report”wsl({ action: "status" })Returns:
Environment(windows,wsl,linux)Running in WSL: true/falseWindows User(when detected)- WSL home + Windows home in both styles
- Path separator, Windows interop availability
- A
Directory Statusblock listing whether each known directory exists
Compact: Env: wsl, WSL: true
3. wsl(action:"autosync_config", enabled:bool, ...)
Section titled “3. wsl(action:"autosync_config", enabled:bool, ...)”Enable or disable auto-sync. Other knobs:
sync_on_write(defaulttrue)sync_on_edit(defaulttrue)silent(defaultfalse)
wsl({ action: "autosync_config", enabled: true, silent: true })If the server is not running inside WSL, enabling auto-sync returns a warning that the feature will be inert.
4. wsl(action:"autosync_status")
Section titled “4. wsl(action:"autosync_status")”Read-only report of the active auto-sync config:
Auto-Sync Status---Status: ENABLEDEnvironment: WSLSync on Write: trueSync on Edit: trueSync on Delete: falseConfig File: /home/user/.config/mcp-filesystem-ultra/autosync.jsonCross-platform path conversion
Section titled “Cross-platform path conversion”wsl is the explicit tool, but every filesystem tool in v4.5.x
auto-converts paths. You almost never need to call wsl for routine
editing — read_file, edit_file, multi_edit, write_file,
delete_file, search_files, etc., all call core.NormalizePath on the
input before any I/O.
The conversion matrix (core/path_converter.go):
| You pass (inside WSL) | Resolves to (on disk) |
|---|---|
/home/user/app.go | /home/user/app.go (no conversion) |
/mnt/c/Users/user/app.go | C:\Users\user\app.go |
C:\Users\user\app.go | /mnt/c/Users/user/app.go |
| You pass (native Windows) | Resolves to (on disk) |
|---|---|
C:\Users\user\app.go | C:\Users\user\app.go |
/mnt/c/Users/user/app.go | C:\Users\user\app.go |
/home/user/app.go | \\wsl$\Ubuntu\home\user\app.go (best-effort) |
The two helpers used everywhere are core.WSLToWindows and
core.WindowsToWSL. They are exported and can be used by the engine
directly. Path conversion respects --allowed-paths — a path that
converts into a denied location is rejected with access denied.
Verify the conversion is working
Section titled “Verify the conversion is working”wsl({ action: "status" })// → look for "Windows Home (WSL style)" and "Windows Home (Windows style)"If both are populated, conversion is wired correctly.
Auto-sync via MCP_WSL_AUTOSYNC (v3.x legacy)
Section titled “Auto-sync via MCP_WSL_AUTOSYNC (v3.x legacy)”The MCP_WSL_AUTOSYNC=true environment variable from v3.x still works in
v4.5.x as a one-liner enable for auto-sync. The mechanism:
- Engine startup reads
MCP_WSL_AUTOSYNC. - If set to
true, auto-sync is enabled with the config-file defaults. wsl(action:"autosync_config")overrides whatever the env var set.
# v3.x one-liner still works:export MCP_WSL_AUTOSYNC=truefilesystem-ultra-v4 --allowed-paths=/home/user/projectsFor anything beyond “just turn it on”, prefer the explicit config file or the
autosync_config action — they survive env-var loss (process restart without
the export) and let you tune sync_on_write / silent / etc.
The config file location (unchanged from v3.4):
~/.config/mcp-filesystem-ultra/autosync.json. See
core/autosync_config.go for the schema.
Allowed-paths and security
Section titled “Allowed-paths and security”Every wsl call validates both sides of the conversion against
--allowed-paths. The conversion runs first, then the check. Implications:
- If
--allowed-pathsis empty, all paths are allowed (default). - If
--allowed-paths=/home/user/projects, awslcopy that resolves to/tmp/foo.gois rejected withaccess denied: one or both paths are outside allowed directories. - Symlinks pointing outside the allowed set are caught by
core.ResolveSymlinks— the resolved canonical path is checked, not the user-supplied path (TOCTOU defense).
This is a hardening introduced in v4.5.5 (the “WSL / Auto-sync security” release). Earlier versions did not validate target paths.
Common workflows
Section titled “Common workflows”Web development in WSL, edit from Windows
Section titled “Web development in WSL, edit from Windows”// One-time: enable auto-sync with silent modewsl({ action: "autosync_config", enabled: true, silent: true })
// From this point, every write_file / edit_file / multi_edit on a WSL path// is silently mirrored to its Windows location. No manual sync needed.Pull a single file from Windows into WSL
Section titled “Pull a single file from Windows into WSL”wsl({ action: "sync", windows_path: "C:\\Users\\user\\Downloads\\data.json", wsl_path: "/home/user/projects/data.json"})// → "OK: Copied to /home/user/projects/data.json"Preview a bulk sync without writing
Section titled “Preview a bulk sync without writing”wsl({ action: "sync", direction: "wsl_to_windows", filter_pattern: "*.go", dry_run: true})// → "Workspace Sync Results ... Mode: DRY RUN (preview only)"Troubleshooting
Section titled “Troubleshooting”“access denied: one or both paths are outside allowed directories”
Section titled ““access denied: one or both paths are outside allowed directories””--allowed-paths rejected one of the converted paths. Either pass
/home/user (or your workspace root) as an allowed path, or adjust the
source/destination to stay inside the existing allowed set.
Auto-sync enabled but nothing is mirrored
Section titled “Auto-sync enabled but nothing is mirrored”- Confirm the server is actually running inside WSL (
wsl(action:"status")). - Confirm auto-sync is enabled (
wsl(action:"autosync_status")). - Confirm the file is in a path under
--allowed-paths. - If
silent: true, there are no logs to grep — temporarily flip tosilent: falseand watch stderr for[AutoSync]lines.
MCP_WSL_AUTOSYNC=true had no effect
Section titled “MCP_WSL_AUTOSYNC=true had no effect”The env var is read once at startup. Set it before launching
filesystem-ultra-v4. After startup, change config with
wsl(action:"autosync_config").
The Windows path differs from what I expected
Section titled “The Windows path differs from what I expected”/mnt/c/... and C:\... are interchangeable. The engine normalises them to
the same canonical form before any I/O. If you see different resolved
paths, you are looking at a case sensitivity issue (Windows is
case-insensitive; the engine preserves the path you gave it on the way out
for display). Always copy paths from list_directory or read_file
output — never retype from memory.
Related
Section titled “Related”- Core Tools — full tool matrix
- edit_file modes and OCC
- Changelog — version history
Version: 4.5.29 Last updated: 2026-07-11