From ef48f58ef1a061b40fd956084141efa4ace798ba Mon Sep 17 00:00:00 2001 From: fengmengqi Date: Thu, 2 Apr 2026 13:52:26 +0800 Subject: [PATCH] =?UTF-8?q?windows=20home=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rust/crates/runtime/src/bash.rs | 39 +++++++++++++++++++++++++++--- rust/crates/runtime/src/config.rs | 7 ++++++ rust/crates/runtime/src/oauth.rs | 12 ++++++--- rust/crates/runtime/src/sandbox.rs | 18 +++++++++++--- 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/rust/crates/runtime/src/bash.rs b/rust/crates/runtime/src/bash.rs index a159ec6..7c2fcd2 100644 --- a/rust/crates/runtime/src/bash.rs +++ b/rust/crates/runtime/src/bash.rs @@ -197,8 +197,16 @@ fn prepare_command( return prepared; } - let mut prepared = Command::new("sh"); - prepared.arg("-lc").arg(command).current_dir(cwd); + let mut prepared = if cfg!(target_os = "windows") && !sh_exists() { + let mut p = Command::new("cmd"); + p.arg("/C").arg(command); + p + } else { + let mut p = Command::new("sh"); + p.arg("-lc").arg(command); + p + }; + prepared.current_dir(cwd); if sandbox_status.filesystem_active { prepared.env("HOME", cwd.join(".sandbox-home")); prepared.env("TMPDIR", cwd.join(".sandbox-tmp")); @@ -206,6 +214,21 @@ fn prepare_command( prepared } +fn sh_exists() -> bool { + env::var_os("PATH").is_some_and(|paths| { + env::split_paths(&paths).any(|path| { + #[cfg(windows)] + { + path.join("sh.exe").exists() || path.join("sh.bat").exists() || path.join("sh").exists() + } + #[cfg(not(windows))] + { + path.join("sh").exists() + } + }) + }) +} + fn prepare_tokio_command( command: &str, cwd: &std::path::Path, @@ -224,8 +247,16 @@ fn prepare_tokio_command( return prepared; } - let mut prepared = TokioCommand::new("sh"); - prepared.arg("-lc").arg(command).current_dir(cwd); + let mut prepared = if cfg!(target_os = "windows") && !sh_exists() { + let mut p = TokioCommand::new("cmd"); + p.arg("/C").arg(command); + p + } else { + let mut p = TokioCommand::new("sh"); + p.arg("-lc").arg(command); + p + }; + prepared.current_dir(cwd); if sandbox_status.filesystem_active { prepared.env("HOME", cwd.join(".sandbox-home")); prepared.env("TMPDIR", cwd.join(".sandbox-tmp")); diff --git a/rust/crates/runtime/src/config.rs b/rust/crates/runtime/src/config.rs index edf1144..60ef53f 100644 --- a/rust/crates/runtime/src/config.rs +++ b/rust/crates/runtime/src/config.rs @@ -170,6 +170,13 @@ impl ConfigLoader { let config_home = std::env::var_os("CLAUDE_CONFIG_HOME") .map(PathBuf::from) .or_else(|| std::env::var_os("HOME").map(|home| PathBuf::from(home).join(".claude"))) + .or_else(|| { + if cfg!(target_os = "windows") { + std::env::var_os("USERPROFILE").map(|home| PathBuf::from(home).join(".claude")) + } else { + None + } + }) .unwrap_or_else(|| PathBuf::from(".claude")); Self { cwd, config_home } } diff --git a/rust/crates/runtime/src/oauth.rs b/rust/crates/runtime/src/oauth.rs index 3f30a00..837bdf2 100644 --- a/rust/crates/runtime/src/oauth.rs +++ b/rust/crates/runtime/src/oauth.rs @@ -327,9 +327,15 @@ fn credentials_home_dir() -> io::Result { if let Some(path) = std::env::var_os("CLAUDE_CONFIG_HOME") { return Ok(PathBuf::from(path)); } - let home = std::env::var_os("HOME") - .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "HOME is not set"))?; - Ok(PathBuf::from(home).join(".claude")) + if let Some(path) = std::env::var_os("HOME") { + return Ok(PathBuf::from(path).join(".claude")); + } + if cfg!(target_os = "windows") { + if let Some(path) = std::env::var_os("USERPROFILE") { + return Ok(PathBuf::from(path).join(".claude")); + } + } + Err(io::Error::new(io::ErrorKind::NotFound, "HOME or USERPROFILE is not set")) } fn read_credentials_root(path: &PathBuf) -> io::Result> { diff --git a/rust/crates/runtime/src/sandbox.rs b/rust/crates/runtime/src/sandbox.rs index 3d834ed..d0054ba 100644 --- a/rust/crates/runtime/src/sandbox.rs +++ b/rust/crates/runtime/src/sandbox.rs @@ -107,11 +107,23 @@ impl SandboxConfig { #[must_use] pub fn detect_container_environment() -> ContainerEnvironment { - let proc_1_cgroup = fs::read_to_string("/proc/1/cgroup").ok(); + let proc_1_cgroup = if cfg!(target_os = "linux") { + fs::read_to_string("/proc/1/cgroup").ok() + } else { + None + }; detect_container_environment_from(SandboxDetectionInputs { env_pairs: env::vars().collect(), - dockerenv_exists: Path::new("/.dockerenv").exists(), - containerenv_exists: Path::new("/run/.containerenv").exists(), + dockerenv_exists: if cfg!(target_os = "linux") { + Path::new("/.dockerenv").exists() + } else { + false + }, + containerenv_exists: if cfg!(target_os = "linux") { + Path::new("/run/.containerenv").exists() + } else { + false + }, proc_1_cgroup: proc_1_cgroup.as_deref(), }) }