-
-
Notifications
You must be signed in to change notification settings - Fork 225
Allow execution in non-TTY environments #236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR enables npkill to run in non-TTY environments (e.g., Git Bash on Windows, CI/CD pipelines, redirected I/O) by removing the TTY requirement check and conditionally calling setRawMode() only when a TTY is available.
Changes:
- Removed the TTY validation check that previously blocked execution in non-TTY environments
- Added conditional check before calling
setRawMode()to prevent crashes when stdin is not a TTY - Added tests to verify the application runs successfully in non-TTY scenarios
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/cli/cli.controller.ts | Removed the TTY requirement check and error exit logic |
| src/cli/services/ui.service.ts | Added conditional check for stdin.isTTY before calling setRawMode() |
| src/constants/messages.constants.ts | Removed the NO_TTY error message constant |
| tests/cli/cli.controller.test.ts | Added TTY handling tests and made test setup properties configurable |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
tests/cli/cli.controller.test.ts
Outdated
| Object.defineProperty(process.stdout, 'isTTY', { value: false }); | ||
| cliController.init(); | ||
| expect(scanSpy).toHaveBeenCalledTimes(1); | ||
| }); | ||
|
|
||
| it('Should exit if terminal is too small', () => { | ||
| Object.defineProperty(process.stdout, 'columns', { value: 10 }); |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test modifies process.stdout.isTTY without making it configurable, which could cause issues if the property needs to be redefined in subsequent tests. The beforeEach hook at lines 199-206 sets these properties as configurable, but this test overrides them without the configurable flag. This inconsistency could lead to test failures or property redefinition errors.
| Object.defineProperty(process.stdout, 'isTTY', { value: false }); | |
| cliController.init(); | |
| expect(scanSpy).toHaveBeenCalledTimes(1); | |
| }); | |
| it('Should exit if terminal is too small', () => { | |
| Object.defineProperty(process.stdout, 'columns', { value: 10 }); | |
| Object.defineProperty(process.stdout, 'isTTY', { | |
| value: false, | |
| configurable: true, | |
| }); | |
| cliController.init(); | |
| expect(scanSpy).toHaveBeenCalledTimes(1); | |
| }); | |
| it('Should exit if terminal is too small', () => { | |
| Object.defineProperty(process.stdout, 'columns', { | |
| value: 10, | |
| configurable: true, | |
| }); |
tests/cli/cli.controller.test.ts
Outdated
| }); | ||
|
|
||
| it('Should exit if terminal is too small', () => { | ||
| Object.defineProperty(process.stdout, 'columns', { value: 10 }); |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test modifies process.stdout.columns without making it configurable, which could cause issues if the property needs to be redefined in subsequent tests. The beforeEach hook at lines 199-206 sets these properties as configurable, but this test overrides them without the configurable flag. This inconsistency could lead to test failures or property redefinition errors.
| Object.defineProperty(process.stdout, 'columns', { value: 10 }); | |
| Object.defineProperty(process.stdout, 'columns', { | |
| value: 10, | |
| configurable: true, | |
| }); |
| if (this.stdin.isTTY) { | ||
| this.stdin.setRawMode(set); | ||
| } |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The conditional check for stdin.isTTY before calling setRawMode is a critical behavior change that lacks dedicated test coverage. While the CLI controller tests verify that the application doesn't crash in non-TTY environments, there are no unit tests for the UiService class itself that verify the setRawMode method correctly handles both TTY and non-TTY scenarios. Consider adding a test file tests/cli/services/ui.service.test.ts to directly test this conditional logic.
This PR resolves the long-standing issue where npkill refused to start in environments that are reported as non-TTY, such as Git Bash on Windows, CI/CD pipelines, or when input/output is redirected.
Previously, the application would exit immediately with a "No TTY supported" error or crash with a TypeError when trying to set the terminal to "raw mode" in a non-interactive shell.
Now no output will be displayed, but no warning will be issued either.
If npkill is run in an environment without stdin, the user will not be able to interact with the application.
Fixes #65 Supersedes #233 (addresses the root cause more safely)