From 4402d9afb06d7bd609eafb4a9ae151d93d7f76d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Andr=C3=A9?= Date: Sun, 15 Mar 2026 01:49:42 +0100 Subject: [PATCH 1/7] fix(tauri): align desktop version metadata Match the Tauri package, Cargo, and bundle version metadata to the current legacy desktop version so About dialogs and installer artifacts stop reporting 0.1.0. --- packages/tauri-app/Cargo.lock | 2 +- packages/tauri-app/src-tauri/Cargo.toml | 2 +- packages/tauri-app/src-tauri/tauri.conf.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/tauri-app/Cargo.lock b/packages/tauri-app/Cargo.lock index e388ea42..750131d6 100644 --- a/packages/tauri-app/Cargo.lock +++ b/packages/tauri-app/Cargo.lock @@ -626,7 +626,7 @@ dependencies = [ [[package]] name = "codenomad-tauri" -version = "0.1.0" +version = "0.12.3" dependencies = [ "anyhow", "dirs 5.0.1", diff --git a/packages/tauri-app/src-tauri/Cargo.toml b/packages/tauri-app/src-tauri/Cargo.toml index f119c846..6d05959a 100644 --- a/packages/tauri-app/src-tauri/Cargo.toml +++ b/packages/tauri-app/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "codenomad-tauri" -version = "0.1.0" +version = "0.12.3" edition = "2021" license = "MIT" diff --git a/packages/tauri-app/src-tauri/tauri.conf.json b/packages/tauri-app/src-tauri/tauri.conf.json index e847379d..65928249 100644 --- a/packages/tauri-app/src-tauri/tauri.conf.json +++ b/packages/tauri-app/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "CodeNomad", - "version": "0.1.0", + "version": "0.12.3", "identifier": "ai.opencode.client", "build": { "beforeDevCommand": "npm run dev:bootstrap", From 87afb06d348e5793e9d297109787319750cd8c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Andr=C3=A9?= Date: Sun, 15 Mar 2026 01:53:31 +0100 Subject: [PATCH 2/7] fix(tauri): restore Windows app identity Set the same explicit AppUserModelID that the legacy Electron app used so Windows taskbar grouping and notification attribution stay consistent in the Tauri desktop build. --- packages/tauri-app/Cargo.lock | 1 + packages/tauri-app/src-tauri/Cargo.toml | 3 +++ packages/tauri-app/src-tauri/src/main.rs | 29 ++++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/packages/tauri-app/Cargo.lock b/packages/tauri-app/Cargo.lock index 750131d6..d5bc8ce7 100644 --- a/packages/tauri-app/Cargo.lock +++ b/packages/tauri-app/Cargo.lock @@ -646,6 +646,7 @@ dependencies = [ "thiserror 1.0.69", "url", "which", + "windows-sys 0.59.0", ] [[package]] diff --git a/packages/tauri-app/src-tauri/Cargo.toml b/packages/tauri-app/src-tauri/Cargo.toml index 6d05959a..f697d3f4 100644 --- a/packages/tauri-app/src-tauri/Cargo.toml +++ b/packages/tauri-app/src-tauri/Cargo.toml @@ -25,3 +25,6 @@ tauri-plugin-opener = "2" url = "2" tauri-plugin-keepawake = "0.1.1" tauri-plugin-notification = "2" + +[target.'cfg(windows)'.dependencies] +windows-sys = { version = "0.59", features = ["Win32_UI_Shell"] } diff --git a/packages/tauri-app/src-tauri/src/main.rs b/packages/tauri-app/src-tauri/src/main.rs index ac402932..832c51f9 100644 --- a/packages/tauri-app/src-tauri/src/main.rs +++ b/packages/tauri-app/src-tauri/src/main.rs @@ -12,8 +12,20 @@ use tauri::{AppHandle, Emitter, Manager, Runtime, Wry}; use tauri_plugin_opener::OpenerExt; use url::Url; +#[cfg(windows)] +use std::ffi::OsStr; +#[cfg(windows)] +use std::iter; +#[cfg(windows)] +use std::os::windows::ffi::OsStrExt; +#[cfg(windows)] +use windows_sys::Win32::UI::Shell::SetCurrentProcessExplicitAppUserModelID; + static QUIT_REQUESTED: AtomicBool = AtomicBool::new(false); +#[cfg(windows)] +const WINDOWS_APP_USER_MODEL_ID: &str = "ai.neuralnomads.codenomad.client"; + #[derive(Clone)] pub struct AppState { pub manager: CliProcessManager, @@ -101,6 +113,22 @@ fn emit_folder_drop_event( } } +#[cfg(windows)] +fn set_windows_app_user_model_id() { + let app_id: Vec = OsStr::new(WINDOWS_APP_USER_MODEL_ID) + .encode_wide() + .chain(iter::once(0)) + .collect(); + + let result = unsafe { SetCurrentProcessExplicitAppUserModelID(app_id.as_ptr()) }; + if result < 0 { + eprintln!("[tauri] failed to set AppUserModelID: {result}"); + } +} + +#[cfg(not(windows))] +fn set_windows_app_user_model_id() {} + fn main() { let navigation_guard: TauriPlugin = PluginBuilder::new("external-link-guard") .on_navigation(|webview, url| intercept_navigation(webview, url)) @@ -116,6 +144,7 @@ fn main() { manager: CliProcessManager::new(), }) .setup(|app| { + set_windows_app_user_model_id(); build_menu(&app.handle())?; let dev_mode = is_dev_mode(); let app_handle = app.handle().clone(); From 9d91ecc649581f5197f81b25963e8a3004a4f040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Andr=C3=A9?= Date: Sun, 15 Mar 2026 20:29:06 +0100 Subject: [PATCH 3/7] fix(tauri): kill Windows CLI process trees on shutdown Use taskkill /T /F for the local server process on Windows so child Node/Bun processes do not survive app shutdown or startup timeouts. --- packages/tauri-app/src-tauri/src/cli_manager.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/tauri-app/src-tauri/src/cli_manager.rs b/packages/tauri-app/src-tauri/src/cli_manager.rs index e193ef83..d4074b1d 100644 --- a/packages/tauri-app/src-tauri/src/cli_manager.rs +++ b/packages/tauri-app/src-tauri/src/cli_manager.rs @@ -36,6 +36,12 @@ const SESSION_COOKIE_NAME: &str = "codenomad_session"; const CLI_STOP_GRACE_SECS: u64 = 30; +#[cfg(windows)] +fn kill_process_tree_windows(pid: u32) { + let _ = Command::new("taskkill") + .args(["/PID", &pid.to_string(), "/T", "/F"]) + .status(); +} fn navigate_main(app: &AppHandle, url: &str) { if let Some(win) = app.webview_windows().get("main") { let mut display = url.to_string(); @@ -352,7 +358,7 @@ impl CliProcessManager { } #[cfg(windows)] { - let _ = child.kill(); + kill_process_tree_windows(child.id()); } let start = Instant::now(); @@ -372,7 +378,7 @@ impl CliProcessManager { } #[cfg(windows)] { - let _ = child.kill(); + kill_process_tree_windows(child.id()); } break; } @@ -537,7 +543,12 @@ impl CliProcessManager { locked.error = Some("CLI did not start in time".to_string()); log_line("timeout waiting for CLI readiness"); if let Some(child) = child_holder_clone.lock().as_mut() { - let _ = child.kill(); + #[cfg(windows)] + kill_process_tree_windows(child.id()); + #[cfg(not(windows))] + { + let _ = child.kill(); + } } let _ = app_clone.emit("cli:error", json!({"message": "CLI did not start in time"})); Self::emit_status(&app_clone, &locked); From 7f631611fdd32e84d5d554a5836e4cbdaf8eac60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Andr=C3=A9?= Date: Mon, 16 Mar 2026 01:44:58 +0100 Subject: [PATCH 4/7] fix(tauri): hide Windows CLI console window Set CREATE_NO_WINDOW on the spawned local CLI process so the packaged Windows Tauri app does not flash an extra console window when it launches Node. --- packages/tauri-app/src-tauri/src/cli_manager.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/tauri-app/src-tauri/src/cli_manager.rs b/packages/tauri-app/src-tauri/src/cli_manager.rs index d4074b1d..4d96f540 100644 --- a/packages/tauri-app/src-tauri/src/cli_manager.rs +++ b/packages/tauri-app/src-tauri/src/cli_manager.rs @@ -17,10 +17,23 @@ use std::thread; use std::time::{Duration, Instant}; use tauri::{webview::cookie::Cookie, AppHandle, Emitter, Manager, Url}; +#[cfg(windows)] +use std::os::windows::process::CommandExt; + +#[cfg(windows)] +const CREATE_NO_WINDOW: u32 = 0x08000000; + fn log_line(message: &str) { println!("[tauri-cli] {message}"); } +fn configure_spawn(command: &mut Command) { + #[cfg(windows)] + { + command.creation_flags(CREATE_NO_WINDOW); + } +} + fn workspace_root() -> Option { std::env::current_dir().ok().and_then(|mut dir| { for _ in 0..3 { @@ -456,6 +469,7 @@ impl CliProcessManager { .env("ELECTRON_RUN_AS_NODE", "1") .stdout(Stdio::piped()) .stderr(Stdio::piped()); + configure_spawn(&mut c); if let Some(ref cwd) = cwd { c.current_dir(cwd); } @@ -468,6 +482,7 @@ impl CliProcessManager { .env("ELECTRON_RUN_AS_NODE", "1") .stdout(Stdio::piped()) .stderr(Stdio::piped()); + configure_spawn(&mut c); if let Some(ref cwd) = cwd { c.current_dir(cwd); } From 6cb6c0af329e1f5eab7bbd0a82c543472f65d2d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Andr=C3=A9?= Date: Tue, 17 Mar 2026 04:27:15 +0100 Subject: [PATCH 5/7] fix(tauri): align desktop bundle identifier --- packages/tauri-app/src-tauri/tauri.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tauri-app/src-tauri/tauri.conf.json b/packages/tauri-app/src-tauri/tauri.conf.json index 65928249..c8f965ff 100644 --- a/packages/tauri-app/src-tauri/tauri.conf.json +++ b/packages/tauri-app/src-tauri/tauri.conf.json @@ -2,7 +2,7 @@ "$schema": "https://schema.tauri.app/config/2", "productName": "CodeNomad", "version": "0.12.3", - "identifier": "ai.opencode.client", + "identifier": "ai.neuralnomads.codenomad.client", "build": { "beforeDevCommand": "npm run dev:bootstrap", "beforeBuildCommand": "npm run bundle:server", From 3a15b311a87ef9517d0b2d15a90ddaacbb13b82d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Andr=C3=A9?= Date: Tue, 17 Mar 2026 04:27:15 +0100 Subject: [PATCH 6/7] fix(tauri): hide taskkill during Windows cleanup --- packages/tauri-app/src-tauri/src/cli_manager.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/tauri-app/src-tauri/src/cli_manager.rs b/packages/tauri-app/src-tauri/src/cli_manager.rs index 4d96f540..127d7dc1 100644 --- a/packages/tauri-app/src-tauri/src/cli_manager.rs +++ b/packages/tauri-app/src-tauri/src/cli_manager.rs @@ -51,9 +51,10 @@ const CLI_STOP_GRACE_SECS: u64 = 30; #[cfg(windows)] fn kill_process_tree_windows(pid: u32) { - let _ = Command::new("taskkill") - .args(["/PID", &pid.to_string(), "/T", "/F"]) - .status(); + let mut command = Command::new("taskkill"); + command.args(["/PID", &pid.to_string(), "/T", "/F"]); + configure_spawn(&mut command); + let _ = command.status(); } fn navigate_main(app: &AppHandle, url: &str) { if let Some(win) = app.webview_windows().get("main") { From 8245f474b8542de71e3724aeba0eecdfee5111ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Andr=C3=A9?= Date: Wed, 18 Mar 2026 20:21:40 +0100 Subject: [PATCH 7/7] fix(tauri): avoid non-Windows spawn warning --- packages/tauri-app/src-tauri/src/cli_manager.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/tauri-app/src-tauri/src/cli_manager.rs b/packages/tauri-app/src-tauri/src/cli_manager.rs index 127d7dc1..c06c3361 100644 --- a/packages/tauri-app/src-tauri/src/cli_manager.rs +++ b/packages/tauri-app/src-tauri/src/cli_manager.rs @@ -27,13 +27,14 @@ fn log_line(message: &str) { println!("[tauri-cli] {message}"); } +#[cfg(windows)] fn configure_spawn(command: &mut Command) { - #[cfg(windows)] - { - command.creation_flags(CREATE_NO_WINDOW); - } + command.creation_flags(CREATE_NO_WINDOW); } +#[cfg(not(windows))] +fn configure_spawn(_command: &mut Command) {} + fn workspace_root() -> Option { std::env::current_dir().ok().and_then(|mut dir| { for _ in 0..3 {