windows home支持

This commit is contained in:
fengmengqi 2026-04-02 13:52:26 +08:00
parent 16bd7df1b4
commit 2639093fe4
4 changed files with 66 additions and 10 deletions

View File

@ -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"));

View File

@ -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 }
}

View File

@ -327,9 +327,15 @@ fn credentials_home_dir() -> io::Result<PathBuf> {
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<Map<String, Value>> {

View File

@ -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(),
})
}