From 951fb4f0217752d9620c9aba1f359b44d9c40bb5 Mon Sep 17 00:00:00 2001 From: mika kuns Date: Thu, 21 May 2026 09:24:29 +0200 Subject: [PATCH] fix(autostart): hide console window on logon via wscript VBS shim Run-key autostart used to register node.exe directly, which made Windows pop a console window at every user logon. Now install-autostart writes a one-line WshShell.Run launcher with vbHide and points the Run-key value at wscript.exe, so the daemon starts truly hidden. Uninstall paths also clean the .vbs file. Co-Authored-By: Claude Opus 4.7 (1M context) --- node/src/autostart/windows.ts | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/node/src/autostart/windows.ts b/node/src/autostart/windows.ts index a3f4729..2ce2c54 100644 --- a/node/src/autostart/windows.ts +++ b/node/src/autostart/windows.ts @@ -35,6 +35,7 @@ const SERVICE_NAME = "ClaudeMailbox"; const RUN_KEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"; const RUN_VALUE = "ClaudeMailbox"; const MARKER_FILE = "autostart-mode"; +const LAUNCHER_FILE = "autostart-launcher.vbs"; function ensureConfigSeeded(opts: AutostartInstallOpts): string { const path = userConfigPath(); @@ -79,9 +80,33 @@ function tryScheduledTaskInstall(opts: AutostartInstallOpts): { ok: boolean; std return { ok: true, stderr: "" }; } +function runKeyLauncherPath(): string { + return join(dirname(userConfigPath()), LAUNCHER_FILE); +} + +function writeRunKeyLauncher(configPath: string): string { + const { node, script } = buildServeCommand(); + const cmd = `"${node}" "${script}" serve --config "${configPath}"`; + const escaped = cmd.replace(/"/g, '""'); + const vbs = + `Set WshShell = CreateObject("WScript.Shell")\r\n` + + `WshShell.Run "${escaped}", 0, False\r\n` + + `Set WshShell = Nothing\r\n`; + const path = runKeyLauncherPath(); + mkdirSync(dirname(path), { recursive: true }); + writeFileSync(path, vbs, "utf8"); + return path; +} + +function removeRunKeyLauncher(): void { + const path = runKeyLauncherPath(); + if (existsSync(path)) rmSync(path, { force: true }); +} + function runKeyInstall(opts: AutostartInstallOpts): void { const configPath = ensureConfigSeeded(opts); - const cmd = buildServeCommandString(configPath); + const launcher = writeRunKeyLauncher(configPath); + const cmd = `wscript.exe "${launcher}"`; const r = run("reg.exe", [ "add", RUN_KEY, @@ -122,6 +147,7 @@ function runKeyUninstall(): void { if (r.status !== 0 && !/unable to find/i.test(r.stderr)) { throw new Error(`reg delete failed (exit ${r.status}): ${r.stderr || r.stdout}`); } + removeRunKeyLauncher(); killRunKeyDaemon(); } @@ -158,6 +184,7 @@ function scheduledTaskUninstall(purge: boolean): void { } // Best-effort Run-key cleanup run("reg.exe", ["delete", RUN_KEY, "/v", RUN_VALUE, "/f"]); + removeRunKeyLauncher(); killRunKeyDaemon(); clearActiveMode(); if (purge) purgeData();