diff --git a/src-tauri/src/claude_binary.rs b/src-tauri/src/claude_binary.rs index 2d1c7e36..2ea43ac7 100644 --- a/src-tauri/src/claude_binary.rs +++ b/src-tauri/src/claude_binary.rs @@ -502,6 +502,37 @@ pub fn create_command_with_env(program: &str) -> Command { } } } + // Also add NVM Node.js when Claude isn't in NVM but needs Node.js + else { + let current_path = std::env::var("PATH").unwrap_or_default(); + if !current_path.contains("/.nvm/versions/node/") { + if let Ok(home) = std::env::var("HOME") { + let nvm_base = PathBuf::from(&home).join(".nvm").join("versions").join("node"); + if nvm_base.exists() { + if let Ok(entries) = std::fs::read_dir(&nvm_base) { + let mut node_versions: Vec = entries + .filter_map(|entry| entry.ok()) + .filter(|entry| entry.file_type().map(|t| t.is_dir()).unwrap_or(false)) + .map(|entry| entry.file_name().to_string_lossy().to_string()) + .collect(); + + // Sort to get latest version (simple string sort works for NVM format) + node_versions.sort_by(|a, b| b.cmp(a)); + + if let Some(latest_version) = node_versions.first() { + let node_bin_path = nvm_base.join(latest_version).join("bin"); + if node_bin_path.exists() { + let node_bin_str = node_bin_path.to_string_lossy(); + let new_path = format!("{}:{}", node_bin_str, current_path); + debug!("Adding NVM Node.js to PATH for Claude execution: {}", node_bin_str); + cmd.env("PATH", new_path); + } + } + } + } + } + } + } // Add Homebrew support if the program is in a Homebrew directory if program.contains("/homebrew/") || program.contains("/opt/homebrew/") { diff --git a/src-tauri/src/commands/claude.rs b/src-tauri/src/commands/claude.rs index 94ad3c55..ad845ee0 100644 --- a/src-tauri/src/commands/claude.rs +++ b/src-tauri/src/commands/claude.rs @@ -226,7 +226,7 @@ fn extract_first_user_message(jsonl_path: &PathBuf) -> (Option, Option Command { // Convert std::process::Command to tokio::process::Command - let _std_cmd = crate::claude_binary::create_command_with_env(program); + let std_cmd = crate::claude_binary::create_command_with_env(program); // Create a new tokio Command from the program path let mut tokio_cmd = Command::new(program); @@ -275,6 +275,19 @@ fn create_command_with_env(program: &str) -> Command { } } } + + // Only use enhanced PATH if Claude is NOT in NVM but needs Node from NVM (our specific fix) + if !program.contains("/.nvm/versions/node/") { + if let Some(enhanced_path) = std_cmd.get_envs().find_map(|(k, v)| { + if k == "PATH" { v.and_then(|val| val.to_str().map(String::from)) } else { None } + }) { + // Only override if the enhanced PATH added NVM paths + if enhanced_path.contains("/.nvm/versions/node/") { + log::debug!("Claude not in NVM but needs Node - using enhanced PATH with NVM: {}", enhanced_path); + tokio_cmd.env("PATH", enhanced_path); + } + } + } tokio_cmd }