Skip to content

fix(loop): guard the top-level --interactive shortcut with a TTY check - #529

Merged
cobusgreyling merged 1 commit into
cobusgreyling:mainfrom
KhaiTrang1995:fix/loop-cli-interactive-tty-guard
Aug 17, 2026
Merged

fix(loop): guard the top-level --interactive shortcut with a TTY check#529
cobusgreyling merged 1 commit into
cobusgreyling:mainfrom
KhaiTrang1995:fix/loop-cli-interactive-tty-guard

Conversation

@KhaiTrang1995

Copy link
Copy Markdown
Contributor

Problem

cmdWizard() (loop wizard --interactive) already gates the interactive
path on process.stdin.isTTY, falling back to printNonInteractiveHelp()
otherwise. The top-level loop --interactive shortcut in main() never
had the same guard: it called runInteractiveWizard() unconditionally.

readline's question() resolves immediately with '' when stdin isn't a
TTY (a CI step, piped input, < /dev/null) instead of waiting for a
human. Without the guard, loop --interactive in a non-interactive
context silently ran the wizard with every prompt answered blank, then
executed the resulting default plan -- loop init . --pattern daily-triage --tool grok against the current directory -- scaffolding
files nobody asked for instead of printing help.

Fix

Mirrors cmdWizard()'s existing gate at the other --interactive entry
point.

Test plan

Added a regression test that runs loop --interactive with stdin
closed (execFileSync's input: '', matching < /dev/null) in an empty
temp directory, asserting it prints the non-interactive help and the
directory stays empty. Confirmed it fails with the wizard prompts
printed and no help text when the guard is stripped, and passes with
the fix. Full clean rebuild + npm test: 11/11 passing.

cmdWizard() (loop wizard --interactive) already gates the interactive
path on process.stdin.isTTY, falling back to printNonInteractiveHelp()
otherwise. The top-level `loop --interactive` shortcut in main() never
had the same guard: it called runInteractiveWizard() unconditionally.

readline's question() resolves immediately with '' when stdin isn't a
TTY (a CI step, piped input, `< /dev/null`) instead of waiting for a
human. Without the guard, `loop --interactive` in a non-interactive
context silently ran the wizard with every prompt answered blank, then
executed the resulting default plan -- `loop init . --pattern
daily-triage --tool grok` against the current directory -- scaffolding
files nobody asked for instead of printing help.

Mirrors cmdWizard()'s existing gate at the other --interactive entry
point.

Test plan: added a regression test that runs `loop --interactive`
with stdin closed (execFileSync's input: '', matching `< /dev/null`)
in an empty temp directory, asserting it prints the non-interactive
help and the directory stays empty. Confirmed it fails with the wizard
prompts printed and no help text when the guard is stripped, and
passes with the fix. Full clean rebuild + npm test: 11/11 passing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@cobusgreyling cobusgreyling left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mirrors the existing cmdWizard() TTY gate. Non-TTY loop --interactive was silently running the default init plan; help + no scaffold is the right behavior. Regression test with closed stdin is solid.

@cobusgreyling
cobusgreyling merged commit eeeb15c into cobusgreyling:main Aug 17, 2026
2 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