Skip to content

WSL support: Cannot import Claude Code sessions from WSL filesystem#34

Open
Codex wants to merge 2 commits intomasterfrom
codex/fix-wsl-import-issue
Open

WSL support: Cannot import Claude Code sessions from WSL filesystem#34
Codex wants to merge 2 commits intomasterfrom
codex/fix-wsl-import-issue

Conversation

@Codex
Copy link

@Codex Codex AI commented Mar 16, 2026

Original prompt

This section details on the original issue you should resolve

<issue_title>WSL support: Cannot import Claude Code sessions from WSL filesystem</issue_title>
<issue_description>## Problem

When running Harnss on Windows with Claude Code installed inside WSL, the "Resume CC Chat" feature shows "No Claude Code sessions found" because session JSONL files are stored in the WSL filesystem (~/.claude/projects/ inside WSL), not on the Windows filesystem.

Root cause

cc-import.ts:getCCProjectDir() constructs the session path using os.homedir() (Windows home) + project path hash. But when the project lives in WSL:

  1. Sessions are at \\wsl$\Ubuntu\home\user\.claude\projects\-home-user\
  2. Harnss looks at C:\Users\user\.claude\projects\... — wrong location
  3. The path hash also differs: WSL project /home/user hashes to -home-user, but Windows path \\wsl$\Ubuntu\home\user would hash differently

Additional issue: Claude binary resolution

claude-binary.ts uses where claude on Windows, which won't find Claude installed inside WSL (~/.local/bin/claude). A WSL fallback (wsl.exe -e which claude) would enable live sessions.

Environment

  • Windows 11 + WSL2 (Ubuntu 24.04)
  • Harnss v0.20.0
  • Claude Code installed in WSL only
  • 752 session JSONL files in ~/.claude/projects/-home-user/

Proposed fix

1. Session import (cc-import.ts)

Detect WSL project paths (\\wsl$\ or \\wsl.localhost\) and resolve the .claude directory from the WSL user's home:

function getCCProjectDir(projectPath: string): string {
  const normalized = projectPath.replace(/\\/g, "/");
  
  // Detect WSL paths: //wsl$/Distro/... or //wsl.localhost/Distro/...
  const wslMatch = normalized.match(/^\/\/wsl(?:\.localhost|\$)\/([^/]+)(\/.*)/i);
  if (wslMatch && process.platform === "win32") {
    const distro = wslMatch[1];
    const wslAbsPath = wslMatch[2];
    const hash = wslAbsPath.replace(/\//g, "-");
    const homeMatch = wslAbsPath.match(/^(\/home\/[^/]+)/);
    const wslHome = homeMatch ? homeMatch[1] : "/root";
    const wslPrefix = `\\\\wsl.localhost\\${distro}`;
    return path.join(wslPrefix, wslHome.replace(/\//g, "\\"), ".claude", "projects", hash);
  }

  const hash = projectPath.replace(/\//g, "-");
  return path.join(os.homedir(), ".claude", "projects", hash);
}

2. Binary resolution (claude-binary.ts)

Add WSL fallback to the resolution chain:

function resolveFromWsl(): ClaudeBinaryResolution | null {
  if (process.platform \!== "win32") return null;
  try {
    const output = execFileSync("wsl.exe", ["-e", "which", "claude"], {
      encoding: "utf-8", timeout: 10000, windowsHide: true,
    }).trim();
    if (output && output.startsWith("/")) {
      return { strategy: "wsl", path: `wsl:${output}` };
    }
    return null;
  } catch { return null; }
}

Then create a .cmd wrapper (wsl.exe -e /path/to/claude %*) that the SDK can spawn.

3. CWD translation

When spawning Claude for a WSL project, translate the CWD:
\\wsl.localhost\Ubuntu\home\user\project/home/user/project

Full patch

I have a working 168-line patch across 3 files. Happy to open a PR if there's interest.</issue_description>

<agent_instructions>Use instructions from the issue and implement proper WSL support.</agent_instructions>

Comments on the Issue (you are @codex[agent] in this section)

@OpenSource03 > I have a working 168-line patch across 3 files. Happy to open a PR if there's interest.

I can fix it, but If you have a fix ready, please feel free to open the PR :)</comment_new>

@Codex Codex AI changed the title [WIP] Fix WSL support for importing Claude Code sessions Add WSL-aware CC session import and Claude binary resolution Mar 16, 2026
@Codex Codex AI requested a review from OpenSource03 March 16, 2026 02:41
@OpenSource03
Copy link
Owner

@codex[agent] make sure there is option in our settings to configure preferred Claude executable.

@chatgpt-codex-connector
Copy link

To use Codex here, create an environment for this repo.

@Codex
Copy link
Author

Codex AI commented Mar 16, 2026

@codex[agent] make sure there is option in our settings to configure preferred Claude executable.

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).

@Codex Codex AI changed the title Add WSL-aware CC session import and Claude binary resolution Addressing PR comments Mar 16, 2026
@OpenSource03 OpenSource03 changed the title Addressing PR comments WSL support: Cannot import Claude Code sessions from WSL filesystem #28 Mar 21, 2026
@OpenSource03 OpenSource03 changed the title WSL support: Cannot import Claude Code sessions from WSL filesystem #28 WSL support: Cannot import Claude Code sessions from WSL filesystem Mar 21, 2026
@OpenSource03 OpenSource03 marked this pull request as ready for review March 21, 2026 02:43
@OpenSource03 OpenSource03 requested a review from Copilot March 21, 2026 02:43
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +24 to +27
export function getLikelyWslHome(unixPath: string): string {
const homeMatch = unixPath.match(/^\/home\/[^/]+/);
if (homeMatch) return homeMatch[0];
return "/root";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 .cmd wrapper 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);
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
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;

Copilot uses AI. Check for mistakes.

function ensureWslWrapper(wslPath: string): string | null {
const wrapperPath = getWslWrapperPath();
const script = `@echo off\r\nwsl.exe -e ${wslPath} %*\r\n`;
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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`;

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +36
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);
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WSL support: Cannot import Claude Code sessions from WSL filesystem

3 participants