From 160e08d4a8ebf1664b25aa82f28acdec65f9adb8 Mon Sep 17 00:00:00 2001 From: megaproxy Date: Sat, 9 May 2026 16:03:40 +0100 Subject: [PATCH 1/2] Suppress console-window flash on subprocess spawn (CREATE_NO_WINDOW); bump 0.1.2 paths::quiet_command sets CREATE_NO_WINDOW (0x08000000) on Windows so short-lived child processes (wsl.exe -l -q, where claude, wsl.exe -d X bash -lc 'command -v claude') don't briefly allocate a real console window and flash on click. Used by both paths.rs and cli_usage.rs. --- package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/src/cli_usage.rs | 9 +++------ src-tauri/src/paths.rs | 19 ++++++++++++++++++- src-tauri/tauri.conf.json | 2 +- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 395c7af..fae27cd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "claude-usage-widget", "private": true, - "version": "0.1.1", + "version": "0.1.2", "type": "module", "scripts": { "dev": "vite", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 350272a..019fe63 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "claude-usage-widget" -version = "0.1.1" +version = "0.1.2" description = "Always-on-top Windows widget visualizing local Claude Code usage" authors = ["megaproxy"] edition = "2021" diff --git a/src-tauri/src/cli_usage.rs b/src-tauri/src/cli_usage.rs index f0d6a7a..26287e6 100644 --- a/src-tauri/src/cli_usage.rs +++ b/src-tauri/src/cli_usage.rs @@ -114,9 +114,8 @@ pub fn autodetect_command() -> Option> { } fn which_exists(name: &str) -> bool { - use std::process::Command; let probe = if cfg!(windows) { "where" } else { "which" }; - Command::new(probe) + crate::paths::quiet_command(probe) .arg(name) .output() .map(|o| o.status.success() && !o.stdout.is_empty()) @@ -124,8 +123,7 @@ fn which_exists(name: &str) -> bool { } fn list_wsl_distros() -> Vec { - use std::process::Command; - let Ok(out) = Command::new("wsl.exe").args(["-l", "-q"]).output() else { + let Ok(out) = crate::paths::quiet_command("wsl.exe").args(["-l", "-q"]).output() else { return Vec::new(); }; if !out.status.success() { @@ -145,8 +143,7 @@ fn list_wsl_distros() -> Vec { } fn probe_claude_in_wsl(distro: &str) -> bool { - use std::process::Command; - Command::new("wsl.exe") + crate::paths::quiet_command("wsl.exe") .args(["-d", distro, "bash", "-lc", "command -v claude"]) .output() .map(|o| o.status.success() && !o.stdout.is_empty()) diff --git a/src-tauri/src/paths.rs b/src-tauri/src/paths.rs index b8d8e6e..dbbea8b 100644 --- a/src-tauri/src/paths.rs +++ b/src-tauri/src/paths.rs @@ -10,6 +10,23 @@ use serde::Serialize; use std::path::{Path, PathBuf}; +/// Construct a `Command` that won't flash a console window on Windows. +/// +/// `Command::new(...).output()` allocates a console for the child process +/// before it exits, which appears as a black flash for short-lived processes +/// like `wsl.exe -l -q` or `where claude`. The CREATE_NO_WINDOW flag (Win32 +/// process-creation flag 0x08000000) suppresses that. +pub fn quiet_command(program: &str) -> std::process::Command { + let mut c = std::process::Command::new(program); + #[cfg(windows)] + { + use std::os::windows::process::CommandExt; + const CREATE_NO_WINDOW: u32 = 0x08000000; + c.creation_flags(CREATE_NO_WINDOW); + } + c +} + #[derive(Debug, Clone, Serialize)] pub struct ResolvedRoots { pub roots: Vec, @@ -24,7 +41,7 @@ pub fn list_wsl_distros() -> anyhow::Result> { return Ok(Vec::new()); } - let out = match std::process::Command::new("wsl.exe") + let out = match quiet_command("wsl.exe") .args(["-l", "-q"]) .output() { diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 667e7a3..68612ba 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Claude Usage Widget", - "version": "0.1.1", + "version": "0.1.2", "identifier": "com.megaproxy.claude-usage-widget", "build": { "beforeDevCommand": "pnpm dev", From a1bbc6f8ba2fb0564b554e43f3edf5c5f44f43b5 Mon Sep 17 00:00:00 2001 From: megaproxy Date: Sat, 9 May 2026 16:05:55 +0100 Subject: [PATCH 2/2] Enforce LF line endings via .gitattributes + ignore tauri-icon's extra outputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the recurring 'Your local changes to Cargo.toml would be overwritten' error on Windows pulls. Git-for-Windows defaults to core.autocrlf=true, which made every text file appear modified vs the LF-stored versions. '* text=auto eol=lf' in .gitattributes overrides autocrlf and forces a stable LF checkout. Also ignores Square*Logo.png, android/, ios/, 64x64.png, icon.png — these are produced by 'pnpm tauri icon' but we ship only the canonical 5 files (32, 128, 128@2x, .ico, .icns). --- .gitattributes | 42 ++++++++++++++++++++++++++++++++++++++++++ .gitignore | 9 +++++++++ 2 files changed, 51 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b94f291 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,42 @@ +# Always check out source files with LF endings, regardless of the user's +# core.autocrlf setting. Without this, Windows clones with core.autocrlf=true +# (the Git-for-Windows default) treat every text file as "modified" because +# Git's stored version is LF but the working copy is CRLF. + +* text=auto eol=lf + +# Explicit text files (belt-and-suspenders). +*.rs text eol=lf +*.toml text eol=lf +*.json text eol=lf +*.ts text eol=lf +*.tsx text eol=lf +*.js text eol=lf +*.svelte text eol=lf +*.css text eol=lf +*.html text eol=lf +*.md text eol=lf +*.yml text eol=lf +*.yaml text eol=lf + +# Shell + Windows scripts keep their native endings. +*.sh text eol=lf +*.ps1 text eol=crlf +*.bat text eol=crlf +*.cmd text eol=crlf + +# Binaries — never touch these. +*.png binary +*.ico binary +*.icns binary +*.jpg binary +*.jpeg binary +*.gif binary +*.exe binary +*.dll binary +*.so binary +*.dylib binary +*.woff binary +*.woff2 binary +*.ttf binary +*.otf binary diff --git a/.gitignore b/.gitignore index d370359..6fe985b 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,15 @@ src-tauri/Cargo.lock *.tsbuildinfo .vite/ +# Extra outputs from `pnpm tauri icon` — we ship only the canonical set +# (32x32.png, 128x128.png, 128x128@2x.png, icon.ico, icon.icns). +src-tauri/icons/64x64.png +src-tauri/icons/icon.png +src-tauri/icons/Square*.png +src-tauri/icons/StoreLogo.png +src-tauri/icons/android/ +src-tauri/icons/ios/ + # Agent working files — meaningful to local Claude Code sessions, noise for # anyone else. Kept out of the public repo (they still live on disk). CLAUDE.md