Skip to content

WSL→Windows cwd path translation when spawning Windows .exe agents from WSL #232

@tbertran

Description

@tbertran

Summary

When the ACPX embedded runtime runs on WSL and spawns a Windows .exe agent (e.g., copilot.exe --acp), the cwd passed to session/new is a Linux path (e.g., /home/user/.openclaw/workspace). Windows agents reject this because they cannot resolve Linux filesystem paths.

Root Cause

asAbsoluteCwd() in acp-client uses path.resolve(cwd), which always produces a POSIX path on Linux/WSL. This POSIX path is then sent directly to the Windows agent process via the ACP session/new request. The Windows agent validates the path using its own (Windows) filesystem and fails.

Reproduction

  1. Run OpenClaw gateway on WSL2 (Ubuntu)
  2. Configure copilot agent with a Windows .exe path:
    "agents": {
      "copilot": {
        "command": "\"/mnt/c/Users/User/AppData/Local/GitHub CLI/copilot/copilot.exe\" --acp --stdio"
      }
    }
  3. Attempt to spawn an ACP session — session/new receives cwd: "/home/user/.openclaw/workspace" and the agent returns:
    {"error": {"code": -32603, "data": {"details": "Directory does not exist or cannot be accessed: /home/user/.openclaw/workspace"}}}

Tested Path Formats

cwd sent to agent Agent accepts?
/home/user/.openclaw/workspace (Linux)
/mnt/c/projects/repo (Linux /mnt/c)
C:\projects\repo (Windows native)
\\wsl.localhost\Ubuntu\home\user (UNC)
C:\Users\User\.openclaw\workspace (via wslpath)

Proposed Fix

When spawning an agent command that resolves to a Windows executable (.exe suffix or /mnt/c/ prefix) from a WSL environment, convert the cwd using wslpath -w before passing it to session/new:

function asAbsoluteCwd(cwd) {
    const resolved = path.resolve(cwd);
    if (isWsl() && isWindowsExeCommand(agentCommand)) {
        return execSync(`wslpath -w "${resolved}"`).toString().trim();
    }
    return resolved;
}

WSL detection: process.platform === "linux" && existsSync("/proc/sys/fs/binfmt_misc/WSLInterop")
Windows exe detection: command basename ends with .exe or resolves under /mnt/c/

wslpath -w handles all cases correctly:

  • Symlinks through /mnt/c/ → native Windows path (C:\...)
  • True WSL paths → UNC path (\\wsl.localhost\Distro\...)
  • Already /mnt/c/ paths → native Windows path

Related

  • openclaw/openclaw#42557 — same class of bug (gateway-side path validation breaks WSL→Windows workflows)
  • #60 — Copilot CLI agent support (now merged as built-in)

Environment

  • WSL2 Ubuntu on Windows 11
  • OpenClaw gateway running in WSL
  • Copilot CLI v1.0.20 (Windows binary, accessed via /mnt/c/)
  • acpx embedded runtime via @openclaw/acpx plugin
  • ACP protocol works correctly — only the cwd path format is the issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions