Skip to content
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
fix(commands): add auto-cleanup for temp config files when terminal c…
…loses

在 open_provider_terminal 功能中添加了临时配置文件的自动清理逻辑,
确保在用户关闭终端窗口时自动删除创建的临时配置文件。

修改内容:
- Linux: 使用 bash -c 嵌套包装脚本,通过 trap EXIT 信号在 shell 退出时清理配置文件
- macOS: 同样使用嵌套 bash + trap 机制来处理清理
- Windows: 保持原有的批处理文件自删除逻辑(del 命令)

技术细节:
- 之前使用 sh -c "...; exec $SHELL" 会导致 trap 失效
- 现在使用 bash -c 'trap ... EXIT; ...; exec bash --norc --noprofile'
- exec 会替换进程但保留 trap 信号处理器
- 当用户关闭终端时,EXIT 信号触发清理操作

影响范围:
- src-tauri/src/commands/misc.rs (launch_terminal_with_env 函数)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
  • Loading branch information
tianrking and claude committed Dec 29, 2025
commit ed9d9b5436a7c18bf2946f49c56d1f6ee4382a9d
73 changes: 56 additions & 17 deletions src-tauri/src/commands/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,17 +410,28 @@ fn launch_terminal_with_env(env_vars: Vec<(String, String)>, provider_id: &str)

#[cfg(target_os = "macos")]
{
// macOS: 使用 Terminal.app 启动 claude
// macOS: 使用 Terminal.app 启动 claude,使用包装脚本来处理清理
let mut terminal_cmd = Command::new("osascript");
terminal_cmd.arg("-e");

let config_file_for_cleanup = config_file.clone();
// 使用 bash 的 trap 来清理配置文件
let config_path_for_script = config_file.to_string_lossy()
.replace('\\', "\\\\")
.replace('"', "\\\"");

let shell_script = format!(
"bash -c 'trap \"rm -f \\\"{}\\\"\" EXIT; echo \"Using provider-specific claude config:\"; echo \"{}\"; claude --settings \"{}\"; exec bash --norc --noprofile'",
config_path_for_script,
config_path_escaped,
config_path_escaped
);

let script = format!(
r#"tell application "Terminal"
activate
do script "echo 'Using provider-specific claude config:' && echo '{}' && claude --settings '{}'; exit"
do script "{}"
end tell"#,
config_path_escaped, config_path_escaped
shell_script.replace('\\', "\\\\").replace('"', "\\\"")
);

terminal_cmd.arg(&script);
Expand All @@ -434,29 +445,46 @@ fn launch_terminal_with_env(env_vars: Vec<(String, String)>, provider_id: &str)

#[cfg(target_os = "linux")]
{
// Linux: 尝试使用常见终端
// Linux: 尝试使用常见终端,使用包装脚本在 shell 退出时清理配置文件
let terminals = [
"gnome-terminal", "konsole", "xfce4-terminal",
"mate-terminal", "lxterminal", "alacritty", "kitty",
];

let mut last_error = String::from("未找到可用的终端");

// 使用 bash 创建包装脚本来处理清理
let config_path_for_bash = config_file.to_string_lossy();
let shell_cmd = format!(
"bash -c 'trap \"rm -f \\\"{}\\\"\" EXIT; echo \"Using provider-specific claude config:\"; echo \"{}\"; claude --settings \"{}\"; exec bash --norc --noprofile'",
config_path_for_bash, config_path_escaped, config_path_escaped
);

for terminal in terminals {
// 检查终端是否存在
if Command::new("which").arg(terminal).output().is_err() {
continue;
}

let result = Command::new(terminal)
.arg("--")
.arg("sh")
.arg("-c")
.arg(&format!(
"echo 'Using provider-specific claude config:' && echo '{}' && claude --settings '{}'; $SHELL",
config_path_escaped, config_path_escaped
))
.spawn();
// 不同的终端使用不同的参数格式
let result = match terminal {
"gnome-terminal" | "mate-terminal" => {
Command::new(terminal)
.arg("--")
.arg("bash")
.arg("-c")
.arg(&shell_cmd)
.spawn()
}
_ => {
Command::new(terminal)
.arg("-e")
.arg("bash")
.arg("-c")
.arg(&shell_cmd)
.spawn()
}
};

match result {
Ok(_) => {
Expand All @@ -478,13 +506,24 @@ fn launch_terminal_with_env(env_vars: Vec<(String, String)>, provider_id: &str)
{
use std::io::Write;

// Windows: 创建临时批处理文件
// Windows: 创建临时批处理文件,并在执行完毕后清理配置文件
let bat_file = temp_dir.join(format!("cc_switch_claude_{}.bat", std::process::id()));

// 转义配置文件路径用于批处理
let config_path_for_batch = config_file.to_string_lossy()
.to_string()
.replace('&', "^&");

let mut content = String::from("@echo off\n");
content.push_str(&format!("echo Using provider-specific claude config:\n"));
content.push_str(&format!("echo {}\n", config_file.to_string_lossy().to_string().replace('&', "^&")));
content.push_str(&format!("claude --settings \"{}\"\n", config_file.to_string_lossy().to_string().replace('&', "^&")));
content.push_str(&format!("echo {}\n", config_path_for_batch));
content.push_str(&format!("claude --settings \"{}\"\n", config_path_for_batch));

// 在 claude 执行完毕后(无论成功与否),删除临时配置文件和批处理文件本身
content.push_str(&format!("del \"{}\" >nul 2>&1\n", config_path_for_batch));
content.push_str(&format!("del \"%%~f0\" >nul 2>&1\n")); // %%~f0 表示批处理文件自身

// 如果 claude 出错,暂停以便用户查看错误信息
content.push_str("if errorlevel 1 (\n");
content.push_str(" echo.\n");
content.push_str(" echo Press any key to close...\n");
Expand Down