WSL support: Cannot import Claude Code sessions from WSL filesystem#34
WSL support: Cannot import Claude Code sessions from WSL filesystem#34
Conversation
|
@codex[agent] make sure there is option in our settings to configure preferred Claude executable. |
|
To use Codex here, create an environment for this repo. |
There’s already a Claude executable picker in Settings → Engines: set “Claude binary source” to Custom and enter the path in the “Custom Claude path” field (present in current build, commit e8652e6). |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e8652e61bb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| export function getLikelyWslHome(unixPath: string): string { | ||
| const homeMatch = unixPath.match(/^\/home\/[^/]+/); | ||
| if (homeMatch) return homeMatch[0]; | ||
| return "/root"; |
There was a problem hiding this comment.
Resolve WSL home reliably for non-/home project paths
Avoid defaulting WSL home to /root when the project path is outside /home/<user>. In cc-import.ts, this helper is used to build the ~/.claude/projects directory, so a project like \\wsl.localhost\Ubuntu\mnt\c\repo maps to \\wsl.localhost\Ubuntu\root\.claude\projects\..., which is typically wrong for normal users and causes cc-sessions:list/import to return no sessions even though they exist under the real user home (for example /home/alice/.claude/projects).
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Adds Windows+WSL interoperability so Claude Code session import and Claude CLI execution can work when Claude is installed and/or projects live inside the WSL filesystem (UNC paths).
Changes:
- Introduces shared WSL UNC parsing/translation helpers (
parseWslPath,maybeToWslPath, etc.). - Adds Windows WSL fallback for locating Claude (
wsl.exe -e which claude) and generates a.cmdwrapper to execute it. - Updates Claude session start/restart CWD handling and Claude Code session import path resolution; adds tests for both WSL helpers and WSL binary resolution.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| electron/src/lib/wsl-path.ts | Adds helper utilities to detect/translate WSL UNC paths and build UNC prefixes. |
| electron/src/lib/claude-binary.ts | Adds WSL binary resolution strategy and generates a Windows .cmd wrapper to run the WSL Claude binary. |
| electron/src/lib/tests/wsl-path.test.ts | Unit tests for WSL UNC parsing, home guessing, and prefix generation. |
| electron/src/lib/tests/claude-binary.test.ts | Extends binary resolution tests to cover WSL fallback and wrapper creation. |
| electron/src/ipc/claude-sessions.ts | Translates WSL UNC CWDs to Unix paths before starting/restarting SDK sessions. |
| electron/src/ipc/cc-import.ts | Uses WSL path parsing to locate .claude/projects/... under WSL home for session import. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| function resolveCwd(raw?: string): string { | ||
| const candidate = raw && raw.trim() ? raw : process.cwd(); | ||
| const translated = maybeToWslPath(candidate); |
There was a problem hiding this comment.
resolveCwd() always translates WSL UNC paths to a Unix path. That’s correct when the Claude executable is the WSL wrapper, but it will break if a Windows-native claude binary is selected (spawn cwd becomes /home/... on Windows). Consider only translating when the resolved Claude binary strategy/path indicates WSL (e.g., when cliPath is the WSL wrapper or resolution strategy is wsl).
| const translated = maybeToWslPath(candidate); | |
| let shouldTranslate = false; | |
| try { | |
| const cliInfo: unknown = getCliPath(); | |
| if (cliInfo && typeof cliInfo === "object") { | |
| const info = cliInfo as { | |
| strategy?: string; | |
| resolutionStrategy?: string; | |
| cliPath?: string; | |
| path?: string; | |
| }; | |
| const strategy = info.strategy ?? info.resolutionStrategy; | |
| const cliPath = info.cliPath ?? info.path; | |
| if (strategy === "wsl") { | |
| shouldTranslate = true; | |
| } else if (typeof cliPath === "string") { | |
| const lowerPath = cliPath.toLowerCase(); | |
| if (lowerPath.includes("wsl")) { | |
| shouldTranslate = true; | |
| } | |
| } | |
| } | |
| } catch { | |
| // If CLI resolution fails for any reason, fall back to no translation. | |
| } | |
| const translated = shouldTranslate ? maybeToWslPath(candidate) : null; |
|
|
||
| function ensureWslWrapper(wslPath: string): string | null { | ||
| const wrapperPath = getWslWrapperPath(); | ||
| const script = `@echo off\r\nwsl.exe -e ${wslPath} %*\r\n`; |
There was a problem hiding this comment.
The generated .cmd wrapper runs wsl.exe -e ${wslPath} %* without quoting/escaping wslPath. If the resolved path contains spaces or special characters (e.g. under /mnt/c/Program Files/...), the wrapper will fail to execute. Quote the command path (and consider a -- separator) when building the wrapper script.
| const script = `@echo off\r\nwsl.exe -e ${wslPath} %*\r\n`; | |
| const quotedWslPath = `"${wslPath.replace(/"/g, '""')}"`; | |
| const script = `@echo off\r\nwsl.exe -e ${quotedWslPath} -- %*\r\n`; |
| const hash = wsl.unixPath.replace(/\//g, "-"); | ||
| const wslHome = getLikelyWslHome(wsl.unixPath); | ||
| const wslPrefix = getWslWindowsPrefix(wsl.distro); | ||
| return path.join(wslPrefix, wslHome.replace(/\//g, "\\"), ".claude", "projects", hash); |
There was a problem hiding this comment.
getLikelyWslHome() infers the WSL user home from the project path and falls back to /root. For WSL projects located outside /home/<user> (e.g. /mnt/c/...), this will point session import at \\wsl.localhost\<distro>\root\.claude\..., which is usually wrong and will still yield “No sessions found”. Consider resolving the actual WSL $HOME for the distro via wsl.exe -d <distro> -e sh -lc 'printf %s "$HOME"' (with caching) instead of guessing from the project path.
Original prompt