From bd04328e402276f69b9e61b6f84e9f30e337ab4a Mon Sep 17 00:00:00 2001 From: Naomi Carrigan Date: Thu, 15 Jan 2026 10:05:22 -0800 Subject: [PATCH] feat: add windows build woooooo (#1) ### Explanation _No response_ ### Issue _No response_ ### Attestations - [x] I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/) - [x] I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/). - [x] My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/). ### Dependencies - [ ] I have pinned the dependencies to a specific patch version. ### Style - [ ] I have run the linter and resolved any errors. - [ ] My pull request uses an appropriate title, matching the conventional commit standards. - [ ] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request. ### Tests - [ ] My contribution adds new code, and I have added tests to cover it. - [ ] My contribution modifies existing code, and I have updated the tests to reflect these changes. - [ ] All new and existing tests pass locally with my changes. - [ ] Code coverage remains at or above the configured threshold. ### Documentation _No response_ ### Versioning Minor - My pull request introduces a new non-breaking feature. Reviewed-on: https://git.nhcarrigan.com/nhcarrigan/hikari-desktop/pulls/1 Co-authored-by: Naomi Carrigan Co-committed-by: Naomi Carrigan --- README.md | 36 +++++++++++++++++++++++++++++++++--- package.json | 5 ++++- src-tauri/src/wsl_bridge.rs | 29 ++++++++++++++++++----------- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index bb4927e..504052a 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,9 @@ sudo pacman -S webkit2gtk-4.1 gtk3 libappindicator-gtk3 xdg-utils ### 3. Install Hikari Desktop -Download the latest release for your distribution: +Download the latest release for your platform. + +#### Linux **AppImage** (any distro): ```bash @@ -64,6 +66,14 @@ sudo dpkg -i hikari-desktop_*.deb sudo rpm -i hikari-desktop-*.rpm ``` +#### Windows + +The Windows build requires WSL (Windows Subsystem for Linux) with Claude Code installed inside WSL. + +1. Install WSL if you haven't already: https://learn.microsoft.com/en-us/windows/wsl/install +2. Install Claude Code inside your WSL distribution (see step 1 above) +3. Run the Windows installer (`.exe` or `.msi`) + ## Character States | State | Trigger | @@ -85,6 +95,20 @@ sudo rpm -i hikari-desktop-*.rpm - Node.js and pnpm - Rust toolchain +#### Windows Cross-Compilation (from Linux/WSL) + +To build Windows binaries from Linux, install the following: + +```bash +sudo apt install nsis lld llvm clang +``` + +You will also need `cargo-xwin`: + +```bash +cargo install cargo-xwin +``` + ### Build ```bash @@ -94,8 +118,14 @@ pnpm install # Development mode pnpm run dev -# Build for Linux -pnpm tauri build +# Build for Linux (AppImage, deb, rpm) +pnpm build:linux + +# Build for Windows (exe/msi/nsis) +pnpm build:windows + +# Build all platforms +pnpm build:all ``` ## Architecture diff --git a/package.json b/package.json index 220f04a..5a9df91 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,10 @@ "preview": "vite preview", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "tauri": "tauri" + "tauri": "tauri", + "build:linux": "tauri build", + "build:windows": "tauri build --runner cargo-xwin --target x86_64-pc-windows-msvc", + "build:all": "pnpm build:linux && pnpm build:windows" }, "license": "MIT", "dependencies": { diff --git a/src-tauri/src/wsl_bridge.rs b/src-tauri/src/wsl_bridge.rs index d3801fc..55badc5 100644 --- a/src-tauri/src/wsl_bridge.rs +++ b/src-tauri/src/wsl_bridge.rs @@ -5,6 +5,9 @@ use std::sync::Arc; use std::thread; use tauri::{AppHandle, Emitter}; +#[cfg(target_os = "windows")] +use std::os::windows::process::CommandExt; + use crate::types::{CharacterState, ClaudeMessage, ConnectionStatus, ContentBlock, StateChangeEvent, OutputEvent, PermissionPromptEvent}; const SEARCH_TOOLS: [&str; 5] = ["Read", "Glob", "Grep", "WebSearch", "WebFetch"]; @@ -116,24 +119,28 @@ impl WslBridge { cmd.current_dir(working_dir); cmd } else { - // Running on Windows - use wsl to call claude + // Running on Windows - use wsl with bash login shell to ensure PATH is loaded eprintln!("[DEBUG] Windows path - using wsl"); let mut cmd = Command::new("wsl"); - let mut args = vec![ - "--cd".to_string(), working_dir.to_string(), - "--".to_string(), "claude".to_string(), - "--output-format".to_string(), "stream-json".to_string(), - "--input-format".to_string(), "stream-json".to_string(), - "--verbose".to_string(), - ]; + + // Build the claude command with all arguments + let mut claude_cmd = format!( + "cd '{}' && claude --output-format stream-json --input-format stream-json --verbose", + working_dir + ); // Add allowed tools if any for tool in &allowed_tools { - args.push("--allowedTools".to_string()); - args.push(tool.clone()); + claude_cmd.push_str(&format!(" --allowedTools '{}'", tool)); } - cmd.args(&args); + // Use bash -lc to load login profile (ensures PATH includes claude) + cmd.args(["-e", "bash", "-lc", &claude_cmd]); + + // Hide the console window on Windows + #[cfg(target_os = "windows")] + cmd.creation_flags(0x08000000); // CREATE_NO_WINDOW + cmd };