[Windows] Three `detached: true` spawns missing `windowsHide` — telemetry flushSync opens a console window on nearly every CLI exit
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 78/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 静か
- 技術スタック
- node.js, typescript
- 領域
- cli
調査の方向性
Inspect the detached spawns in src/telemetry/transport.ts, src/utils/openBrowser.ts, and src/commands/previewLifecycle.ts, comparing their options with the existing windowsHide handling in src/utils/autoUpdate.ts. Verify on Windows that telemetry flushes, background preview, and browser launches no longer open console windows while preserving their existing detached behavior.
索引モデルが issue の本文から書いたものです。
説明
Describe the bug
On Windows, console windows pop up during ordinary CLI use — not just during renders. This is a follow-up to #3379 (ffmpeg, fixed) and is distinct from #3430 (chrome-headless-shell, still open): those two cover console-subsystem binaries, whereas this one is about detached: true spawns of Node itself.
Node's docs are explicit about the mechanism:
On Windows, setting
options.detachedtotruemakes it possible for the child process to continue running after the parent exits. The child will have its own console window.
child_process.spawn() defaults windowsHide to false, so any detached: true spawn opens a visible console window on Windows unless windowsHide: true is passed.
Root cause
packages/cli v0.8.13 has four detached: true spawns. Three are missing windowsHide: true:
| Source | What it spawns | windowsHide |
|---|---|---|
src/telemetry/transport.ts (flushSync) |
node -e "fetch(...)" → PostHog |
❌ missing |
src/utils/openBrowser.ts (openBrowser) |
user's browser | ❌ missing |
src/commands/previewLifecycle.ts |
background preview server | ❌ missing |
src/utils/autoUpdate.ts |
update check | ✅ present |
autoUpdate.ts already gets this right, which makes the other three look like oversights rather than intent.
The worst offender: telemetry flushSync
flushSync() is the process-exit flush path. Because it can't await an HTTP POST during shutdown, it hands the payload to a detached Node process to deliver after the parent dies:
function flushSync() {
const payload = buildPayload(eventQueue);
if (payload == null) return;
eventQueue = [];
try {
const child = spawn(
process.execPath,
["-e", `fetch(${JSON.stringify(`${POSTHOG_HOST}/batch/`)},{...})`],
{ detached: true, stdio: "ignore" } // <-- no windowsHide
);
child.unref();
} catch {}
}
The strategy itself is sound — the only thing missing is windowsHide: true.
Impact is amplified by how the CLI is actually used. Agent-driven workflows invoke many short-lived commands (check, lint, keyframes, capture, snapshot, beats, preview), and each invocation that exits with queued events opens its own console window. My ~/.hyperframes/config.json shows commandCount: 1350, which is a lot of windows. Unlike #3430 this isn't render-only — it fires on nearly every command, including read-only ones.
Steps to reproduce
- On Windows, ensure telemetry is on (default):
telemetryEnabled: truein~/.hyperframes/config.json - Run any short command, e.g.
npx hyperframes check .ornpx hyperframes lint . - Watch the desktop/taskbar as the command exits — a console window flashes open
- Run several commands in sequence; you get one window per exit
Setting HYPERFRAMES_NO_TELEMETRY=1 (or DO_NOT_TRACK=1) makes the flashing stop, which isolates the telemetry spawn as the cause.
For the other two sites: hyperframes preview without --foreground spawns the detached background server (one window), and without --no-open spawns the browser via options.browserPath (one more).
Expected behavior
No console window appears for any of these background spawns.
Actual behavior
A console window opens per detached spawn — in the telemetry case, on nearly every CLI invocation.
Suggested fix
Add windowsHide: true at the three call sites, matching what autoUpdate.ts already does:
// src/telemetry/transport.ts
const child = spawn(process.execPath, ["-e", script], {
detached: true,
stdio: "ignore",
windowsHide: true,
});
// src/utils/openBrowser.ts
const child = spawn7(options.browserPath, args, {
detached: true,
stdio: "ignore",
windowsHide: true,
});
// src/commands/previewLifecycle.ts
child = spawn17(execPath, args, {
detached: true,
stdio: ["ignore", logFd, logFd],
env: process.env,
windowsHide: true,
});
windowsHide is a no-op on macOS/Linux, so it's safe to apply unconditionally — same rationale as the #3379 fix.
Given that #3379, #3430, and this issue are all the same class of defect, it may be worth a small shared spawn helper that applies windowsHide: true by default, plus a lint rule that flags a bare detached: true without it.
Environment
hyperframes 0.8.13 (latest)
Node.js v24.15.0 (win32 x64)
OS Microsoft Windows 10 Home 10.0.19045 (build 19045)
Install npx (_npx cache)
Additional context
Verified by static analysis of the shipped dist/cli.js in [email protected] — all four detached: true sites were inspected directly, along with every windowsHide occurrence. All ffmpeg/ffprobe spawns correctly carry windowsHide: true with the explanatory comment added by the #3379 fix, so that regression has not returned.
Related: #3379 (ffmpeg, closed/fixed) · #3430 (chrome-headless-shell, open)
- 主要言語
- TypeScript
- スター
- 54.1k
- フォーク
- 4.9k
- 平均マージ
- 7時間 18分
- マージ済み PR(30日)
- 784
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
heygen-com/hyperframes のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
heygen-com/hyperframes#5027 ·
メンテナーはふだん 1 日以内に返信
-
fix(producer): propagate useGpu to HDR layered streaming encoder対応中かも @Monster-GM が 2 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 87/100
heygen-com/hyperframes#5002 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
heygen-com/hyperframes#4702 · コメント 1 件 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
Studio catalog prompt editor has no accessible name対応中かも @lorenzozanee が 12 日前に担当しました。 オープンbug difficulty/easy triage/ready
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
heygen-com/hyperframes#4384 ·
メンテナーはふだん 1 日以内に返信
-
lint: validate composition variables declared on supported root elements再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンbug difficulty/easy triage/ready
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
heygen-com/hyperframes#4383 ·
メンテナーはふだん 1 日以内に返信
heygen-com/hyperframes の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
umbraco/Umbraco-CMS-MCP-Dev#512 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
wimpysworld/sidra#290 ·
メンテナーはふだん 1 日以内に返信
-
defuFn invokes function values for inherited default properties対応中かも @xiehuanyi が今日担当しました。 オープン
難易度 1/5 1時間未満 初心者へのやさしさ 85/100
-
feature request good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
TabularisDB/tabularis#853 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1時間未満 初心者へのやさしさ 85/100
capricorn86/happy-dom#2474 ·
メンテナーはふだん 2 日以内に返信