Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src-tauri/src/claude_binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> = 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/") {
Expand Down
15 changes: 14 additions & 1 deletion src-tauri/src/commands/claude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ fn extract_first_user_message(jsonl_path: &PathBuf) -> (Option<String>, Option<S
/// This ensures commands like Claude can find Node.js and other dependencies
fn create_command_with_env(program: &str) -> 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);
Expand Down Expand Up @@ -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
}
Expand Down