[Windows] Three `detached: true` spawns missing `windowsHide` — telemetry flushSync opens a console window on nearly every CLI exit
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 78/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- node.js, typescript
- Lĩnh vực
- cli
Hướng nghiên cứu
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.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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)
- Ngôn ngữ chính
- TypeScript
- Star
- 54.1k
- Fork
- 4.9k
- Merge trung bình
- 7 giờ 18 phút
- Pull request đã merge (30 ngày)
- 784
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của heygen-com/hyperframes
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
heygen-com/hyperframes#5027 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
fix(producer): propagate useGpu to HDR layered streaming encoderCó thể đã có người làm @Monster-GM đã nhận 1 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 87/100
heygen-com/hyperframes#5002 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
heygen-com/hyperframes#4702 · 1 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Studio catalog prompt editor has no accessible nameCó thể đã có người làm @lorenzozanee đã nhận 12 ngày trước. Đang mởbug difficulty/easy triage/ready
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
heygen-com/hyperframes#4384 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
lint: validate composition variables declared on supported root elementsCó thể làm lại được Pull request cho issue này đã bị đóng mà không được merge. Đang mởbug difficulty/easy triage/ready
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
heygen-com/hyperframes#4383 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của heygen-com/hyperframes
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 83/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Signals (Failure Detector): a tool call and its own execution are reported as a repeated callĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
platformatic/mcp#208 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
🐛 bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
margelo/react-native-vision-camera#4211 ·
Maintainer thường phản hồi trong vòng 4 ngày