You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
confirm() reads the reply via defaultReadLine(), a byte-by-byte fs.readSync(0, ...) loop whose bare catch returns null on any error.
buildRuntime() evaluates !!process.stdin.isTTY before the prompt. The process.stdin getter instantiates the tty stream, and libuv flips fd 0 to non-blocking as a side effect. Verified in-process via /proc/self/fdinfo/0: O_NONBLOCK flips false → true right after touching process.stdin, and the next readSync(0) throws EAGAIN.
Reproduced under a pty (script -qec): with process.stdin touched, readSync(0) throws EAGAIN instantly; without the touch it blocks and reads input correctly.
Bisected via git log -S "readSync(0": regression introduced by chore(biome): cover and format all TypeScript files #5020, which rewrote defaultReadLine from a child-shell read (sh -c 'IFS= read -r reply', immune because libuv resets child stdio to blocking) to the in-process readSync loop.
Ruled out user env: NEMOCLAW_NON_INTERACTIVE=1 / NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 unset in a fresh shell → identical behavior. confirm() never reads these vars.
Existing unit tests inject readLine via deps and CI uses --yes, so the real stdin path was never exercised.
Description
Running nemoclaw uninstall (without --yes) on a Linux terminal prints the banner and Proceed? [y/N], then immediately prints Aborted. and exits — the user never gets a chance to type. Same behavior via bash uninstall.sh. Expected: the prompt waits for y/n.
Root cause: buildRuntime() touches process.stdin (to detect a TTY), which switches fd 0 to non-blocking mode (libuv side effect). The subsequent fs.readSync(0) then throws EAGAIN ("no data yet") because the user hasn't typed in the microseconds after the prompt printed, and the catch-all treats it as EOF → null → Aborted.. Deterministic on every Linux TTY.
Regression from #5020 ("chore(biome): cover and format all TypeScript files"), which rewrote defaultReadLine from a child-shell read to the in-process readSync loop. Affects both prompts in the uninstall flow (Proceed? [y/N] and the user-data Also remove them? [y/N]).
Impact: interactive uninstall is unusable on Linux since #5020 merged (2026-06-09). Workaround: nemoclaw uninstall --yes.
Observe Proceed? [y/N] followed instantly by Aborted. — no keystroke possible. Same with bash uninstall.sh.
Environment
OS: DGX OS (Ubuntu-based) — also reproduced on a second Ubuntu workstation
Hardware: DGX Spark (spark-b028); not hardware-specific
Node.js: v22.22.3
Docker: 29.1.3 - not involved (bug is in the CLI prompt layer)
NemoClaw: v0.0.62-4-gbf817c40d
Debug Output
Not applicable — the failure is in the CLI confirm-prompt layer, before any sandbox/gateway/Docker interaction. No sandbox is required to reproduce;`nemoclaw debug` bundle contains nothing relevant to this path.
Logs
Terminal transcript (three attempts, all instant-abort):
local-hple@spark-b028:~/NemoClaw$ nemoclaw uninstall
Running local uninstall script: /localhome/local-hple/NemoClaw/uninstall.sh
NemoClaw Uninstaller
This will remove all NemoClaw resources.
...
Proceed? [y/N]
Aborted.
local-hple@spark-b028:~/NemoClaw$ bash uninstall.sh
...
Proceed? [y/N]
Aborted.
local-hple@spark-b028:~/NemoClaw$ nemoclaw --version
nemoclaw v0.0.62-4-gbf817c40d
Minimal mechanism proof under a pty (input arrives 1 s after read starts):
--- with process.stdin touched (what buildRuntime does) ---
isTTY: true
READ ERR: EAGAIN <- thrown instantly, misread as EOF
--- without touching process.stdin ---
READ ok: 1 "y"<- blocks and reads correctly
/proc/self/fdinfo/0: O_NONBLOCK = false ->true after `void process.stdin.isTTY`
Checklist
I confirmed this bug is reproducible
I searched existing issues and this is not a duplicate
Agent Diagnostic
Investigated with Claude Code against the repo source:
nemoclaw uninstall→uninstall.sh(thin wrapper) →dist/nemoclaw.js internal uninstall run-plan→src/lib/actions/uninstall/run-plan.ts.confirm()reads the reply viadefaultReadLine(), a byte-by-bytefs.readSync(0, ...)loop whose barecatchreturnsnullon any error.buildRuntime()evaluates!!process.stdin.isTTYbefore the prompt. Theprocess.stdingetter instantiates the tty stream, and libuv flips fd 0 to non-blocking as a side effect. Verified in-process via/proc/self/fdinfo/0:O_NONBLOCKflipsfalse → trueright after touchingprocess.stdin, and the nextreadSync(0)throwsEAGAIN.script -qec): withprocess.stdintouched,readSync(0)throwsEAGAINinstantly; without the touch it blocks and reads input correctly.git log -S "readSync(0": regression introduced by chore(biome): cover and format all TypeScript files #5020, which rewrotedefaultReadLinefrom a child-shell read (sh -c 'IFS= read -r reply', immune because libuv resets child stdio to blocking) to the in-processreadSyncloop.NEMOCLAW_NON_INTERACTIVE=1/NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1unset in a fresh shell → identical behavior.confirm()never reads these vars.readLinevia deps and CI uses--yes, so the real stdin path was never exercised.Description
Running
nemoclaw uninstall(without--yes) on a Linux terminal prints the banner andProceed? [y/N], then immediately printsAborted.and exits — the user never gets a chance to type. Same behavior viabash uninstall.sh. Expected: the prompt waits fory/n.Root cause:
buildRuntime()touchesprocess.stdin(to detect a TTY), which switches fd 0 to non-blocking mode (libuv side effect). The subsequentfs.readSync(0)then throwsEAGAIN("no data yet") because the user hasn't typed in the microseconds after the prompt printed, and the catch-all treats it as EOF →null→Aborted.. Deterministic on every Linux TTY.Regression from #5020 ("chore(biome): cover and format all TypeScript files"), which rewrote
defaultReadLinefrom a child-shell read to the in-processreadSyncloop. Affects both prompts in the uninstall flow (Proceed? [y/N]and the user-dataAlso remove them? [y/N]).Impact: interactive uninstall is unusable on Linux since #5020 merged (2026-06-09). Workaround:
nemoclaw uninstall --yes.Fix PR: #NNNN
Reproduction Steps
v0.0.62-4-gbf817c40d).nemoclaw uninstall(no--yes).Proceed? [y/N]followed instantly byAborted.— no keystroke possible. Same withbash uninstall.sh.Environment
Debug Output
Logs
Checklist