Skip to content

fix(cli): sh1pt remove silently uninstalls nothing on non-TTY stdin - #999

Merged
ralyodio merged 1 commit into
profullstack:masterfrom
WNZhao:fix/remove-non-tty-skip-uninstall
Aug 30, 2026
Merged

fix(cli): sh1pt remove silently uninstalls nothing on non-TTY stdin#999
ralyodio merged 1 commit into
profullstack:masterfrom
WNZhao:fix/remove-non-tty-skip-uninstall

Conversation

@WNZhao

@WNZhao WNZhao commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Bug

sh1pt remove (alias uninstall) asks "Also delete ~/.config/sh1pt/ ...?" via prompts() before calling run(argv) — the line that actually shells out to npm/pnpm/etc. to uninstall the package. On non-TTY stdin (CI, < /dev/null, a piped uninstall script) prompts() never resolves for the same reason described in #992: it never receives input that would resolve or cancel it, and once nothing else is keeping the event loop alive Node exits on its own — abandoning the pending prompt before run(argv) ever runs.

Net effect: sh1pt remove in a non-interactive shell exits 0 having uninstalled nothing at all, silently.

Fix

Skip the prompt when there's no TTY and keep its existing safe default (initial: false, same as passing --keep-config) instead of hanging in front of the actual uninstall — so the primary effect of the command (actually uninstalling) still happens, and the config directory is conservatively kept rather than guessed at.

Tests

Added packages/cli/src/commands/self.test.ts (4 tests, mocking prompts, ../installer.js, ../run-command.js, node:fs, @profullstack/sh1pt-core, and process.exit — no real package-manager command or filesystem delete is ever executed):

  • non-TTY → run(argv) still executes, prompts never called
  • non-TTY → ~/.config/sh1pt/ is kept (not deleted) by default
  • TTY → still prompts and honors the answer (existing behavior preserved)
  • --keep-config → skips the prompt entirely regardless of TTY

pnpm test → 716/716 test files, 3619/3620 tests passing (1 pre-existing unrelated skip). pnpm --filter @profullstack/sh1pt typecheck passes clean.

Related: #992 (same root cause, different command — sh1pt init).

removeCmd asks "also delete ~/.config/sh1pt/?" via prompts() before calling
run(argv), the line that actually shells out to the package manager to
uninstall sh1pt. prompts() reads keystrokes from stdin; when stdin is not a
TTY (CI, `< /dev/null`, a piped uninstall script) it never receives input
that resolves or cancels the prompt. Once nothing else keeps the event loop
alive, Node exits on its own, abandoning the still-pending `await prompts(...)`
before run(argv) further down ever executes — so `sh1pt remove` used to exit 0
having uninstalled nothing at all in a non-interactive shell.

Skip the prompt when there's no TTY and keep its existing safe default
(`initial: false`, i.e. behave like --keep-config) instead of hanging in
front of the actual uninstall, so the primary "remove sh1pt" effect still
happens. --keep-config already bypasses the question the same way.
@ralyodio
ralyodio merged commit d24f081 into profullstack:master Aug 30, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants