Skip to content

Conversation

@zaldih
Copy link
Member

@zaldih zaldih commented Jan 10, 2026

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)

Copy link

Copilot AI left a 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.

Comment on lines 410 to 416
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 });
Copy link

Copilot AI Jan 10, 2026

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.

Suggested change
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,
});

Copilot uses AI. Check for mistakes.
});

it('Should exit if terminal is too small', () => {
Object.defineProperty(process.stdout, 'columns', { value: 10 });
Copy link

Copilot AI Jan 10, 2026

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.

Suggested change
Object.defineProperty(process.stdout, 'columns', { value: 10 });
Object.defineProperty(process.stdout, 'columns', {
value: 10,
configurable: true,
});

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +12
if (this.stdin.isTTY) {
this.stdin.setRawMode(set);
}
Copy link

Copilot AI Jan 10, 2026

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.

Copilot uses AI. Check for mistakes.
@zaldih zaldih merged commit 693e37f into main Jan 11, 2026
19 checks passed
@zaldih zaldih deleted the fix/remove-tty-notice branch January 11, 2026 16:12
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.

Windows Git Bash Support

2 participants