Skip to content

feat(wsl): add WSL project runtime support#245

Open
Duducoco wants to merge 3 commits into
hanshuaikang:mainfrom
Duducoco:main
Open

feat(wsl): add WSL project runtime support#245
Duducoco wants to merge 3 commits into
hanshuaikang:mainfrom
Duducoco:main

Conversation

@Duducoco

@Duducoco Duducoco commented Jun 8, 2026

Copy link
Copy Markdown

feat(wsl): add WSL project runtime support

Summary

This PR adds first-class WSL project support to Nezha. Users can now open Linux projects from a selected WSL distribution, persist them as WSL-backed projects, and run Nezha workflows against the Linux filesystem and Linux toolchain instead of the Windows host environment.

The implementation introduces a runtime abstraction for projects, then threads that runtime through the frontend and Tauri backend so agent tasks, embedded shells, file browsing, Git operations, session discovery, settings, and task persistence all understand whether a project is local or WSL-backed.

This is intentionally implemented as an MVP without WSL hook installation. WSL projects use session-file polling and structured session locations instead of injecting local Windows hooks into distro-local Claude/Codex configuration.

Why

Before this change, Nezha assumed that every project path and tool invocation belonged to the Windows host environment:

  • Project paths were stored as Windows absolute paths.
  • Claude Code and Codex were launched directly from Windows PATH.
  • Git, file reads, file writes, shell sessions, config files, and session JSONL paths were all resolved as local Windows paths.
  • Claude/Codex session discovery assumed Windows-side session roots.

That breaks for users whose real development environment is inside WSL. In that setup:

  • The project path is a Linux path such as /home/user/project.
  • The Windows-visible path may be a UNC path such as \\wsl.localhost\Rocky8\home\user\project.
  • Claude Code, Codex, Git, package managers, and shell startup files are installed inside the distro.
  • Agent PATH often depends on interactive shell initialization through Linuxbrew, nvm, or shell aliases.
  • Session files are created inside the distro and must be read through WSL/UNC-aware paths.

This PR makes Nezha preserve that runtime boundary instead of flattening WSL projects into ordinary Windows paths.

What Changed

Project Runtime Model

Added a runtime model that distinguishes local projects from WSL projects.

New frontend types include:

  • ProjectRuntime
  • SessionLocation
  • WslDistroInfo
  • WslProjectValidation

Projects can now carry runtime metadata such as:

  • WSL distro name
  • Linux project path
  • optional UNC path
  • configured shell

This lets the UI keep displaying and persisting a normal project while still routing backend operations through WSL when needed.

WSL Runtime Backend Module

Added src-tauri/src/runtime.rs to centralize WSL-specific helpers and Tauri commands.

The new runtime module handles:

  • Listing WSL distros.
  • Checking distro health.
  • Converting Linux paths to UNC paths.
  • Parsing UNC WSL paths.
  • Validating Linux project paths inside a distro.
  • Detecting Claude Code and Codex versions inside WSL.
  • Wrapping command execution through wsl.exe.

The WSL agent detection path uses the configured shell in interactive mode so user shell initialization is respected. This is required for setups where claude or codex are exposed through Linuxbrew, nvm, or shell aliases rather than the distro's minimal non-interactive PATH.

App Settings: WSL Panel

Added a WSL settings panel under application settings.

The panel supports:

  • Enabling WSL project support.
  • Choosing a default WSL distribution.
  • Choosing the default WSL shell.
  • Checking distro health.
  • Detecting Git, Claude Code, and Codex from inside the selected distro.

The settings panel now correctly handles the save_app_settings command returning void, keeping the current settings state after save instead of replacing it with an empty value.

The check result reads backend camelCase fields correctly:

  • gitPath
  • claudeVersion
  • codexVersion

Welcome Page: Open WSL Projects

The welcome flow now supports WSL-backed project creation/opening.

The WSL project flow:

  • Lists available distros.
  • Uses the configured default distro when available.
  • Accepts Linux project paths.
  • Validates that the path exists and is a directory.
  • Detects whether Git is available in the distro.
  • Stores the project with WSL runtime metadata.

WSL projects are deduplicated by distro and Linux path, not just by Windows path.

Agent Launching in WSL

Agent task execution now respects the project runtime.

For WSL projects, Claude Code and Codex are launched through wsl.exe with:

  • the selected distro
  • the Linux project directory
  • the configured shell
  • interactive shell initialization

This fixes cases where wsl.exe --exec claude fails because the command only exists after .bashrc, Linuxbrew, nvm, or aliases are loaded.

Important behavior:

  • WSL agent invocations use distro-local claude and codex.
  • Windows agent path settings are not reused for WSL projects.
  • Windows-only hook injection is skipped for WSL projects.
  • Attachment paths passed to agents are converted from Windows project-relative paths to Linux project paths.

Embedded Shell in WSL

The embedded shell panel now opens the configured WSL shell inside the Linux project directory when the active project is WSL-backed.

This makes the shell environment match the selected project runtime rather than dropping users into a Windows shell for a Linux project.

Git Operations in WSL

Git operations now accept runtime context and route WSL project commands through the selected distro.

The Git integration supports WSL-aware behavior for:

  • status
  • branch listing
  • branch switching
  • branch creation
  • log
  • diff
  • stage / unstage
  • commit
  • push
  • pull
  • generated commit messages
  • worktree-related command guards

The intent is that Git panels reflect what users would see when running Git inside the WSL project directory.

File System Operations in WSL

File operations now support WSL project paths and UNC-backed reads.

Updated areas include:

  • project file listing
  • directory reads
  • text file reads
  • image previews
  • file writes
  • file explorer interactions
  • file viewer interactions
  • search context behavior

The backend preserves path validation so WSL file operations remain scoped to the selected project.

Project Config in WSL

Project config commands now accept runtime context.

This allows .nezha/config.toml and related project-level config reads/writes to happen in the correct project environment for WSL-backed projects.

Session Discovery and Reading

Session handling now supports structured session locations.

New behavior:

  • WSL session paths can be represented as SessionLocation::Wsl.
  • Legacy local session paths are still supported.
  • Claude and Codex session discovery can resolve WSL session roots.
  • Session message reading accepts either legacy sessionPath or structured sessionLocation.
  • Session export and analytics can read WSL session files through the resolved path.

For WSL projects, session discovery avoids injecting /status into the live terminal. Instead, it polls WSL session files and binds the most recent matching session. This prevents the UI from visibly typing /status into Claude/Codex interactive sessions.

Task Persistence

Task storage now preserves structured session location fields:

  • claudeSessionLocation
  • codexSessionLocation

The existing session path fields remain for backward compatibility.

UI Routing and Props

Runtime metadata is threaded through the main UI so the correct backend behavior is selected from project context.

Updated areas include:

  • App.tsx
  • ProjectPage
  • WelcomePage
  • SettingsDialog
  • file explorer components
  • Git panels
  • running task view
  • session view
  • shell terminal panel
  • new task flow
  • project rail
  • task panel

Localized UI Strings

Added WSL-related localization entries for the settings panel, welcome flow, validation states, unsupported worktree flow, and runtime labels.

Important Implementation Details

Interactive Shell Detection

WSL agent detection and WSL agent launching use an interactive shell command path because many real installations expose claude and codex through shell initialization.

This avoids the failure mode where:

wsl.exe -d <distro> --exec claude

fails with:

execvpe(claude) failed: No such file or directory

even though claude works in the user's WSL terminal.

WSL Hooks Are Intentionally Disabled

This PR does not install or use WSL-specific hooks.

For WSL projects:

  • hook readiness is treated as unavailable
  • task/session tracking falls back to polling
  • Nezha does not modify distro-local Claude/Codex hook configuration

This keeps the MVP isolated from Windows hook configuration and avoids mixing host-local and distro-local event paths.

Session Polling Avoids /status Injection

The local fallback path can use /status to identify sessions. In WSL, that was visible and disruptive in interactive terminals.

This PR changes WSL-backed tasks to poll session files instead. That prevents Nezha from typing /status into the user's live Claude/Codex session.

Worktrees Are Guarded for WSL

The new-task worktree launch path is blocked for WSL projects in this MVP. Worktree support requires additional Linux-path-aware branch and filesystem handling and should be implemented separately.

Files Added

  • src-tauri/src/runtime.rs
  • src/components/app-settings/WslPanel.tsx
  • src/projectRuntime.ts
  • pnpm-workspace.yaml

Files Updated

Major backend updates:

  • src-tauri/src/pty.rs
  • src-tauri/src/session.rs
  • src-tauri/src/git.rs
  • src-tauri/src/fs.rs
  • src-tauri/src/config.rs
  • src-tauri/src/storage.rs
  • src-tauri/src/app_settings.rs
  • src-tauri/src/agent_assist.rs
  • src-tauri/src/analytics.rs
  • src-tauri/src/lib.rs

Major frontend updates:

  • src/App.tsx
  • src/types.ts
  • src/components/WelcomePage.tsx
  • src/components/AppSettingsDialog.tsx
  • src/components/SettingsDialog.tsx
  • src/components/ProjectPage.tsx
  • src/components/RunningView.tsx
  • src/components/SessionView.tsx
  • src/components/ShellTerminalPanel.tsx
  • src/components/FileExplorer.tsx
  • src/components/FileViewer.tsx
  • src/components/GitChanges.tsx
  • src/components/GitDiffViewer.tsx
  • src/components/GitHistory.tsx
  • src/i18n.tsx

Manual Verification Performed

Verified on Windows with WSL distro Rocky8.

WSL shell verification:

  • git resolves to /usr/bin/git
  • claude resolves to /home/linuxbrew/.linuxbrew/bin/claude
  • codex resolves to /home/linuxbrew/.linuxbrew/bin/codex
  • Claude Code version detected: 2.1.168 (Claude Code)
  • Codex version detected: codex-cli 0.136.0

Verified behavior:

  • WSL settings can save without leaving the panel stuck in loading state.
  • WSL settings check can detect distro Git, Claude Code, and Codex.
  • WSL agent launch resolves user-shell commands that fail under direct wsl.exe --exec claude.
  • WSL Claude/Codex sessions no longer receive an injected /status command from Nezha.
  • Debug desktop app was restarted after backend changes.

Automated / Command Verification

Passed:

cargo check

Passed:

tsc --noEmit

Also checked before committing:

git diff --check

Not completed:

pnpm build

pnpm build was blocked by the local pnpm dependency policy:

[ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: esbuild@0.27.4

This appears to be an environment/package-manager approval issue rather than a TypeScript or Rust compile failure.

Risks

Session Matching Is Polling-Based for WSL

WSL sessions are discovered by polling session files instead of hook events. This is less immediate than hooks and may be less precise if multiple WSL agent sessions are launched simultaneously in the same project.

WSL Path Handling Is Broadly Threaded

This PR touches many UI and backend paths because project runtime affects nearly every workflow. The highest-risk areas are Git actions, file writes, and session path resolution.

WSL Worktrees Are Not Supported Yet

Worktree launch is guarded for WSL projects. Users should create/run tasks in the main WSL project path until WSL worktree support is implemented.

WSL Proxy Warnings May Still Appear

WSL can print localhost proxy warnings independently of Nezha. This PR fixes command resolution and session pollution, but does not change WSL networking/proxy configuration.

Backward Compatibility

Local Windows projects continue to use the existing behavior.

Existing fields are retained:

  • claudeSessionPath
  • codexSessionPath

New fields are additive:

  • runtime
  • claudeSessionLocation
  • codexSessionLocation

This avoids forcing an immediate migration of existing local project/task data.

Follow-up Work

Recommended follow-ups:

  • Add WSL-specific integration tests for runtime command wrapping.
  • Add targeted tests for WSL path conversion and session location serialization.
  • Add WSL hook support as a separate phase.
  • Add WSL worktree support.
  • Improve UX around WSL proxy warnings and distro health diagnostics.
  • Consider debouncing WSL settings health checks if users click repeatedly.
  • Consider a project-level runtime indicator in more views so users can clearly see whether they are operating in Windows or WSL.

PR Checklist

  • Add WSL runtime model.
  • Add WSL settings panel.
  • Add WSL project open flow.
  • Route agent launch through WSL.
  • Route Git operations through WSL.
  • Route file operations through WSL.
  • Support structured WSL session locations.
  • Avoid /status injection for WSL session discovery.
  • Preserve local project behavior.
  • Run Rust compile check.
  • Run TypeScript type check.
  • Run full pnpm build once local pnpm build-script approval is resolved.

- add WSL project selection, settings, and runtime metadata
- run agents, git, filesystem, and shell commands in WSL contexts
- support WSL session discovery and structured session locations
@hanshuaikang

Copy link
Copy Markdown
Owner

这个PR 的改动有点过于大了,请问在群里吗~

@Duducoco

Duducoco commented Jun 8, 2026

Copy link
Copy Markdown
Author

这个PR 的改动有点过于大了,请问在群里吗~

我不在群里,我也发现改动的文件太多,我想办法看如何减少一些改动

Duducoco added 2 commits June 8, 2026 19:53
- run WSL detection commands without creating console windows
- hide session home lookups during WSL session discovery
- share interactive shell helpers across WSL agent launch paths
- remove optional WSL labels and copy actions from ancillary UI
- drop accidental pnpm workspace placeholder
@Duducoco

Duducoco commented Jun 8, 2026

Copy link
Copy Markdown
Author

我已经重新审查并收敛了 WSL 相关改动,尽量减少了受影响的文件数量。目前保留的改动基本都是 WSL 功能链路必需的部分。

这组 WSL 提交主要包含以下能力:

  • 支持创建和打开 WSL 项目,可选择发行版并校验 Linux 项目路径。
  • 为项目增加 runtime 信息,用于区分本地项目和 WSL 项目。
  • 文件浏览、文件读取/写入、图片预览、文件搜索支持 WSL 路径。
  • Git 状态、diff、历史、分支、提交、push/pull 等操作支持在 WSL 项目内执行。
  • Claude Code / Codex 任务可以在 WSL 发行版内启动,并通过交互式 shell 读取 WSL 内的 PATH、nvm、Linuxbrew 等环境。
  • 支持 WSL 项目的内嵌 shell。
  • 支持 WSL 会话发现、会话读取、导出和 token/tool metrics 统计。
  • 修复后台探测 WSL/agent 时 Windows cmd 窗口闪现的问题。
  • 收敛了一些重复的 WSL agent 启动逻辑,并移除了非必要的辅助 UI 改动。

剩下的文件改动主要是为了把 runtime 参数传递到 Tauri 命令边界,以及让文件、Git、终端、任务和会话这些核心模块真正能在 WSL 项目中工作

@hanshuaikang

Copy link
Copy Markdown
Owner

@Duducoco pr 太大,我可能需要花时间评估一下引入 wsl 支持这个特性~,感谢贡献代码

@Duducoco

Duducoco commented Jun 8, 2026

Copy link
Copy Markdown
Author

@Duducoco pr 太大,我可能需要花时间评估一下引入 wsl 支持这个特性~,感谢贡献代码

好的,感谢作者。不知后续有没有支持ssh的计划

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.

2 participants