diff --git a/src-tauri/src/commands/misc.rs b/src-tauri/src/commands/misc.rs index 5001e1f37..623166e5a 100644 --- a/src-tauri/src/commands/misc.rs +++ b/src-tauri/src/commands/misc.rs @@ -948,6 +948,7 @@ exec bash --norc --noprofile "kitty" => launch_macos_open_app("kitty", &script_file, false), "ghostty" => launch_macos_open_app("Ghostty", &script_file, true), "wezterm" => launch_macos_open_app("WezTerm", &script_file, true), + "kaku" => launch_macos_open_app("Kaku", &script_file, true), _ => launch_macos_terminal_app(&script_file), // "terminal" or default }; diff --git a/src-tauri/src/session_manager/terminal/mod.rs b/src-tauri/src/session_manager/terminal/mod.rs index ab13466ba..3e35df30e 100644 --- a/src-tauri/src/session_manager/terminal/mod.rs +++ b/src-tauri/src/session_manager/terminal/mod.rs @@ -20,6 +20,7 @@ pub fn launch_terminal( "ghostty" => launch_ghostty(command, cwd), "kitty" => launch_kitty(command, cwd), "wezterm" => launch_wezterm(command, cwd), + "kaku" => launch_kaku(command, cwd), "alacritty" => launch_alacritty(command, cwd), "custom" => launch_custom(command, cwd, custom_config), _ => Err(format!("Unsupported terminal target: {target}")), @@ -153,25 +154,10 @@ fn launch_kitty(command: &str, cwd: Option<&str>) -> Result<(), String> { fn launch_wezterm(command: &str, cwd: Option<&str>) -> Result<(), String> { // wezterm start --cwd ... -- command // To invoke via `open`, we use `open -na "WezTerm" --args start ...` - - let full_command = build_shell_command(command, None); - - let mut args = vec!["-na", "WezTerm", "--args", "start"]; - - if let Some(dir) = cwd { - args.push("--cwd"); - args.push(dir); - } - - // Invoke shell to run the command string (to handle pipes, etc) - let shell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/zsh".to_string()); - args.push("--"); - args.push(&shell); - args.push("-c"); - args.push(&full_command); + let args = build_wezterm_compatible_args("WezTerm", command, cwd); let status = Command::new("open") - .args(&args) + .args(args.iter().map(String::as_str)) .status() .map_err(|e| format!("Failed to launch WezTerm: {e}"))?; @@ -182,6 +168,54 @@ fn launch_wezterm(command: &str, cwd: Option<&str>) -> Result<(), String> { } } +fn launch_kaku(command: &str, cwd: Option<&str>) -> Result<(), String> { + // Kaku is a WezTerm-derived terminal and keeps a compatible `start` entrypoint. + let args = build_wezterm_compatible_args("Kaku", command, cwd); + + let status = Command::new("open") + .args(args.iter().map(String::as_str)) + .status() + .map_err(|e| format!("Failed to launch Kaku: {e}"))?; + + if status.success() { + Ok(()) + } else { + Err("Failed to launch Kaku.".to_string()) + } +} + +fn build_wezterm_compatible_args(app_name: &str, command: &str, cwd: Option<&str>) -> Vec { + let shell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/zsh".to_string()); + build_wezterm_compatible_args_with_shell(app_name, command, cwd, &shell) +} + +fn build_wezterm_compatible_args_with_shell( + app_name: &str, + command: &str, + cwd: Option<&str>, + shell: &str, +) -> Vec { + let full_command = build_shell_command(command, None); + let mut args = vec![ + "-na".to_string(), + app_name.to_string(), + "--args".to_string(), + "start".to_string(), + ]; + + if let Some(dir) = cwd { + args.push("--cwd".to_string()); + args.push(dir.to_string()); + } + + // Invoke shell to run the command string (to handle pipes, etc) + args.push("--".to_string()); + args.push(shell.to_string()); + args.push("-c".to_string()); + args.push(full_command); + args +} + fn launch_alacritty(command: &str, cwd: Option<&str>) -> Result<(), String> { // Alacritty: open -na Alacritty --args --working-directory ... -e shell -c command let full_command = build_shell_command(command, None); @@ -305,4 +339,30 @@ mod tests { "raw:echo foo\\\\\\\\bar\\npwd\\n" ); } + + #[test] + fn wezterm_compatible_terminals_use_start_and_cwd_arguments() { + let args = build_wezterm_compatible_args_with_shell( + "Kaku", + "claude --resume abc-123", + Some("/tmp/project dir"), + "/bin/zsh", + ); + + assert_eq!( + args, + vec![ + "-na".to_string(), + "Kaku".to_string(), + "--args".to_string(), + "start".to_string(), + "--cwd".to_string(), + "/tmp/project dir".to_string(), + "--".to_string(), + "/bin/zsh".to_string(), + "-c".to_string(), + "claude --resume abc-123".to_string(), + ] + ); + } } diff --git a/src-tauri/src/settings.rs b/src-tauri/src/settings.rs index 22e415a4c..c9b4a4b41 100644 --- a/src-tauri/src/settings.rs +++ b/src-tauri/src/settings.rs @@ -273,7 +273,7 @@ pub struct AppSettings { // ===== 终端设置 ===== /// 首选终端应用(可选,默认使用系统默认终端) - /// - macOS: "terminal" | "iterm2" | "warp" | "alacritty" | "kitty" | "ghostty" + /// - macOS: "terminal" | "iterm2" | "warp" | "alacritty" | "kitty" | "ghostty" | "wezterm" | "kaku" /// - Windows: "cmd" | "powershell" | "wt" (Windows Terminal) /// - Linux: "gnome-terminal" | "konsole" | "xfce4-terminal" | "alacritty" | "kitty" | "ghostty" #[serde(default, skip_serializing_if = "Option::is_none")] diff --git a/src/components/settings/TerminalSettings.tsx b/src/components/settings/TerminalSettings.tsx index c1d62a158..4cf43d418 100644 --- a/src/components/settings/TerminalSettings.tsx +++ b/src/components/settings/TerminalSettings.tsx @@ -16,6 +16,7 @@ const MACOS_TERMINALS = [ { value: "kitty", labelKey: "settings.terminal.options.macos.kitty" }, { value: "ghostty", labelKey: "settings.terminal.options.macos.ghostty" }, { value: "wezterm", labelKey: "settings.terminal.options.macos.wezterm" }, + { value: "kaku", labelKey: "settings.terminal.options.macos.kaku" }, ] as const; const WINDOWS_TERMINALS = [ diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 5a0f16b42..9da0596f3 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -535,7 +535,8 @@ "alacritty": "Alacritty", "kitty": "Kitty", "ghostty": "Ghostty", - "wezterm": "WezTerm" + "wezterm": "WezTerm", + "kaku": "Kaku" }, "windows": { "cmd": "Command Prompt", diff --git a/src/i18n/locales/ja.json b/src/i18n/locales/ja.json index bb0c8bf43..35597a69f 100644 --- a/src/i18n/locales/ja.json +++ b/src/i18n/locales/ja.json @@ -535,7 +535,8 @@ "alacritty": "Alacritty", "kitty": "Kitty", "ghostty": "Ghostty", - "wezterm": "WezTerm" + "wezterm": "WezTerm", + "kaku": "Kaku" }, "windows": { "cmd": "コマンドプロンプト", diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index 8696647dd..37cc8478c 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -535,7 +535,8 @@ "alacritty": "Alacritty", "kitty": "Kitty", "ghostty": "Ghostty", - "wezterm": "WezTerm" + "wezterm": "WezTerm", + "kaku": "Kaku" }, "windows": { "cmd": "命令提示符", diff --git a/src/types.ts b/src/types.ts index c1b674418..90cb06a22 100644 --- a/src/types.ts +++ b/src/types.ts @@ -313,7 +313,7 @@ export interface Settings { // ===== 终端设置 ===== // 首选终端应用(可选,默认使用系统默认终端) - // macOS: "terminal" | "iterm2" | "warp" | "alacritty" | "kitty" | "ghostty" + // macOS: "terminal" | "iterm2" | "warp" | "alacritty" | "kitty" | "ghostty" | "wezterm" | "kaku" // Windows: "cmd" | "powershell" | "wt" // Linux: "gnome-terminal" | "konsole" | "xfce4-terminal" | "alacritty" | "kitty" | "ghostty" preferredTerminal?: string;