Problem
On Windows, the Startup folder login item (OpenClaw Gateway.cmd) launches the gateway using:
```batch
start "" /min cmd.exe /d /c C:\Users<user>.openclaw\gateway.cmd
```
The `/min` flag minimizes the window but does not suppress rendering — Windows still composites the `cmd.exe` frame before minimizing it. On Windows 11 this produces a visible white/black terminal flash on screen at every login.
Root location: `src/daemon/schtasks.ts` → `renderStartupLaunchCommand()` / `buildStartupLauncherScript()`
This is the startup-folder variant of the same root cause in #57682 (visible CMD window during `openclaw update` gateway restart).
Environment
- Windows 11 Home 10.0.26200
- OpenClaw 2026.4.21
- Startup folder item: `%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\OpenClaw Gateway.cmd`
Expected Behaviour
Gateway starts at login with zero visible window — no flash, no minimized taskbar entry.
Proposed Fix
Replace `start "" /min cmd.exe` with a `wscript.exe` VBScript shim. `wscript.exe` with window style `0` suppresses the window before the process is created — the frame never enters the compositor. This is the canonical Windows method for truly invisible background process launch.
The fix lives entirely in `src/daemon/schtasks.ts`. Instead of one `.cmd` in the Startup folder, generate two files:
- `OpenClaw Gateway.cmd` — unchanged path/name (service detector still finds it), now delegates to the `.vbs`
- `OpenClaw Gateway.vbs` — the silent launcher
`src/daemon/schtasks.ts` — `renderStartupLaunchCommand()`:
```typescript
// BEFORE
function renderStartupLaunchCommand(scriptPath: string): string {
return `start "" /min cmd.exe /d /c ${quoteCmdScriptArg(scriptPath)}`;
}
function buildStartupLauncherScript(opts: StartupScriptOpts): string {
const lines = ['@echo off'];
if (opts.description) lines.push(`rem ${opts.description}`);
lines.push(renderStartupLaunchCommand(opts.scriptPath));
return lines.join('\r\n') + '\r\n';
}
```
```typescript
// AFTER
const VBS_LAUNCHER_FILENAME = 'OpenClaw Gateway.vbs';
// window style 0 = hidden — frame is never created, zero flash
function buildStartupVbsLauncher(gatewayCmdPath: string): string {
const escaped = gatewayCmdPath.replace(/"/g, '""');
return [
`Set sh = CreateObject("WScript.Shell")`,
`sh.Run "cmd.exe /d /c """ & "${escaped}" & """", 0, False`,
].join('\r\n') + '\r\n';
}
function buildStartupLauncherScript(opts: StartupScriptOpts): string {
const vbsPath = path.join(path.dirname(opts.startupItemPath), VBS_LAUNCHER_FILENAME);
const lines = ['@echo off'];
if (opts.description) lines.push(`rem ${opts.description}`);
// delegate to .vbs so service detector still finds the .cmd at its registered path
lines.push(`wscript.exe //nologo "${vbsPath}"`);
return lines.join('\r\n') + '\r\n';
}
export { buildStartupVbsLauncher, VBS_LAUNCHER_FILENAME };
```
Install path (wherever `installStartupFolderItem` writes the `.cmd`): also write the `.vbs` alongside it.
Uninstall path: also remove the `.vbs`.
Why Not Other Approaches
| Approach |
Problem |
| `start /min` (current) |
Window flashes before minimizing |
| PowerShell `-WindowStyle Hidden` |
PowerShell host itself flashes |
| Task Scheduler hidden flag |
Unreliable on interactive logon sessions |
| `CREATE_NO_WINDOW` in Node spawn |
Only applies to Node-spawned processes, not Startup folder items launched by Windows shell |
| VBScript window style 0 |
✅ No window ever created — zero flash |
Verified
- `wscript.exe` confirmed present on Windows 11 and all supported Windows versions
- `wscript.exe //nologo` suppresses the VBScript logo banner
- The `.cmd` path stays unchanged — `openclaw gateway status` service detection is unaffected
- On VBScript deprecation (Windows 11 24H2+): if `wscript.exe` is eventually removed, the fallback should be a small compiled shim. Suggest adding a `// TODO(windows-vbs-deprecation)` at the generation site.
Related
Problem
On Windows, the Startup folder login item (
OpenClaw Gateway.cmd) launches the gateway using:```batch
start "" /min cmd.exe /d /c C:\Users<user>.openclaw\gateway.cmd
```
The `/min` flag minimizes the window but does not suppress rendering — Windows still composites the `cmd.exe` frame before minimizing it. On Windows 11 this produces a visible white/black terminal flash on screen at every login.
Root location: `src/daemon/schtasks.ts` → `renderStartupLaunchCommand()` / `buildStartupLauncherScript()`
This is the startup-folder variant of the same root cause in #57682 (visible CMD window during `openclaw update` gateway restart).
Environment
Expected Behaviour
Gateway starts at login with zero visible window — no flash, no minimized taskbar entry.
Proposed Fix
Replace `start "" /min cmd.exe` with a `wscript.exe` VBScript shim. `wscript.exe` with window style `0` suppresses the window before the process is created — the frame never enters the compositor. This is the canonical Windows method for truly invisible background process launch.
The fix lives entirely in `src/daemon/schtasks.ts`. Instead of one `.cmd` in the Startup folder, generate two files:
`src/daemon/schtasks.ts` — `renderStartupLaunchCommand()`:
```typescript
// BEFORE
function renderStartupLaunchCommand(scriptPath: string): string {
return `start "" /min cmd.exe /d /c ${quoteCmdScriptArg(scriptPath)}`;
}
function buildStartupLauncherScript(opts: StartupScriptOpts): string {
const lines = ['@echo off'];
if (opts.description) lines.push(`rem ${opts.description}`);
lines.push(renderStartupLaunchCommand(opts.scriptPath));
return lines.join('\r\n') + '\r\n';
}
```
```typescript
// AFTER
const VBS_LAUNCHER_FILENAME = 'OpenClaw Gateway.vbs';
// window style 0 = hidden — frame is never created, zero flash
function buildStartupVbsLauncher(gatewayCmdPath: string): string {
const escaped = gatewayCmdPath.replace(/"/g, '""');
return [
`Set sh = CreateObject("WScript.Shell")`,
`sh.Run "cmd.exe /d /c """ & "${escaped}" & """", 0, False`,
].join('\r\n') + '\r\n';
}
function buildStartupLauncherScript(opts: StartupScriptOpts): string {
const vbsPath = path.join(path.dirname(opts.startupItemPath), VBS_LAUNCHER_FILENAME);
const lines = ['@echo off'];
if (opts.description) lines.push(`rem ${opts.description}`);
// delegate to .vbs so service detector still finds the .cmd at its registered path
lines.push(`wscript.exe //nologo "${vbsPath}"`);
return lines.join('\r\n') + '\r\n';
}
export { buildStartupVbsLauncher, VBS_LAUNCHER_FILENAME };
```
Install path (wherever `installStartupFolderItem` writes the `.cmd`): also write the `.vbs` alongside it.
Uninstall path: also remove the `.vbs`.
Why Not Other Approaches
Verified
Related